##// END OF EJS Templates
Remove remaining references held by test suite, so that xdel test passes.
Thomas Kluyver -
Show More
@@ -1,456 +1,471 b''
1 """Tests for various magic functions.
1 """Tests for various magic functions.
2
2
3 Needs to be run by nose (to make ipython session available).
3 Needs to be run by nose (to make ipython session available).
4 """
4 """
5 from __future__ import absolute_import
5 from __future__ import absolute_import
6
6
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Imports
8 # Imports
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 import os
11 import os
12 import sys
12 import sys
13 import tempfile
13 import tempfile
14 import types
14 import types
15 from cStringIO import StringIO
15 from cStringIO import StringIO
16
16
17 import nose.tools as nt
17 import nose.tools as nt
18
18
19 from IPython.utils.path import get_long_path_name
19 from IPython.utils.path import get_long_path_name
20 from IPython.testing import decorators as dec
20 from IPython.testing import decorators as dec
21 from IPython.testing import tools as tt
21 from IPython.testing import tools as tt
22
22
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24 # Test functions begin
24 # Test functions begin
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26 def test_rehashx():
26 def test_rehashx():
27 # clear up everything
27 # clear up everything
28 _ip = get_ipython()
28 _ip = get_ipython()
29 _ip.alias_manager.alias_table.clear()
29 _ip.alias_manager.alias_table.clear()
30 del _ip.db['syscmdlist']
30 del _ip.db['syscmdlist']
31
31
32 _ip.magic('rehashx')
32 _ip.magic('rehashx')
33 # Practically ALL ipython development systems will have more than 10 aliases
33 # Practically ALL ipython development systems will have more than 10 aliases
34
34
35 yield (nt.assert_true, len(_ip.alias_manager.alias_table) > 10)
35 yield (nt.assert_true, len(_ip.alias_manager.alias_table) > 10)
36 for key, val in _ip.alias_manager.alias_table.iteritems():
36 for key, val in _ip.alias_manager.alias_table.iteritems():
37 # we must strip dots from alias names
37 # we must strip dots from alias names
38 nt.assert_true('.' not in key)
38 nt.assert_true('.' not in key)
39
39
40 # rehashx must fill up syscmdlist
40 # rehashx must fill up syscmdlist
41 scoms = _ip.db['syscmdlist']
41 scoms = _ip.db['syscmdlist']
42 yield (nt.assert_true, len(scoms) > 10)
42 yield (nt.assert_true, len(scoms) > 10)
43
43
44
44
45 def test_magic_parse_options():
45 def test_magic_parse_options():
46 """Test that we don't mangle paths when parsing magic options."""
46 """Test that we don't mangle paths when parsing magic options."""
47 ip = get_ipython()
47 ip = get_ipython()
48 path = 'c:\\x'
48 path = 'c:\\x'
49 opts = ip.parse_options('-f %s' % path,'f:')[0]
49 opts = ip.parse_options('-f %s' % path,'f:')[0]
50 # argv splitting is os-dependent
50 # argv splitting is os-dependent
51 if os.name == 'posix':
51 if os.name == 'posix':
52 expected = 'c:x'
52 expected = 'c:x'
53 else:
53 else:
54 expected = path
54 expected = path
55 nt.assert_equals(opts['f'], expected)
55 nt.assert_equals(opts['f'], expected)
56
56
57
57
58 def doctest_hist_f():
58 def doctest_hist_f():
59 """Test %hist -f with temporary filename.
59 """Test %hist -f with temporary filename.
60
60
61 In [9]: import tempfile
61 In [9]: import tempfile
62
62
63 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
63 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
64
64
65 In [11]: %hist -nl -f $tfile 3
65 In [11]: %hist -nl -f $tfile 3
66
66
67 In [13]: import os; os.unlink(tfile)
67 In [13]: import os; os.unlink(tfile)
68 """
68 """
69
69
70
70
71 def doctest_hist_r():
71 def doctest_hist_r():
72 """Test %hist -r
72 """Test %hist -r
73
73
74 XXX - This test is not recording the output correctly. For some reason, in
74 XXX - This test is not recording the output correctly. For some reason, in
75 testing mode the raw history isn't getting populated. No idea why.
75 testing mode the raw history isn't getting populated. No idea why.
76 Disabling the output checking for now, though at least we do run it.
76 Disabling the output checking for now, though at least we do run it.
77
77
78 In [1]: 'hist' in _ip.lsmagic()
78 In [1]: 'hist' in _ip.lsmagic()
79 Out[1]: True
79 Out[1]: True
80
80
81 In [2]: x=1
81 In [2]: x=1
82
82
83 In [3]: %hist -rl 2
83 In [3]: %hist -rl 2
84 x=1 # random
84 x=1 # random
85 %hist -r 2
85 %hist -r 2
86 """
86 """
87
87
88 def doctest_hist_op():
88 def doctest_hist_op():
89 """Test %hist -op
89 """Test %hist -op
90
90
91 In [1]: class b:
91 In [1]: class b:
92 ...: pass
92 ...: pass
93 ...:
93 ...:
94
94
95 In [2]: class s(b):
95 In [2]: class s(b):
96 ...: def __str__(self):
96 ...: def __str__(self):
97 ...: return 's'
97 ...: return 's'
98 ...:
98 ...:
99
99
100 In [3]:
100 In [3]:
101
101
102 In [4]: class r(b):
102 In [4]: class r(b):
103 ...: def __repr__(self):
103 ...: def __repr__(self):
104 ...: return 'r'
104 ...: return 'r'
105 ...:
105 ...:
106
106
107 In [5]: class sr(s,r): pass
107 In [5]: class sr(s,r): pass
108 ...:
108 ...:
109
109
110 In [6]:
110 In [6]:
111
111
112 In [7]: bb=b()
112 In [7]: bb=b()
113
113
114 In [8]: ss=s()
114 In [8]: ss=s()
115
115
116 In [9]: rr=r()
116 In [9]: rr=r()
117
117
118 In [10]: ssrr=sr()
118 In [10]: ssrr=sr()
119
119
120 In [11]: bb
120 In [11]: bb
121 Out[11]: <...b instance at ...>
121 Out[11]: <...b instance at ...>
122
122
123 In [12]: ss
123 In [12]: ss
124 Out[12]: <...s instance at ...>
124 Out[12]: <...s instance at ...>
125
125
126 In [13]:
126 In [13]:
127
127
128 In [14]: %hist -op
128 In [14]: %hist -op
129 >>> class b:
129 >>> class b:
130 ... pass
130 ... pass
131 ...
131 ...
132 >>> class s(b):
132 >>> class s(b):
133 ... def __str__(self):
133 ... def __str__(self):
134 ... return 's'
134 ... return 's'
135 ...
135 ...
136 >>>
136 >>>
137 >>> class r(b):
137 >>> class r(b):
138 ... def __repr__(self):
138 ... def __repr__(self):
139 ... return 'r'
139 ... return 'r'
140 ...
140 ...
141 >>> class sr(s,r): pass
141 >>> class sr(s,r): pass
142 >>>
142 >>>
143 >>> bb=b()
143 >>> bb=b()
144 >>> ss=s()
144 >>> ss=s()
145 >>> rr=r()
145 >>> rr=r()
146 >>> ssrr=sr()
146 >>> ssrr=sr()
147 >>> bb
147 >>> bb
148 <...b instance at ...>
148 <...b instance at ...>
149 >>> ss
149 >>> ss
150 <...s instance at ...>
150 <...s instance at ...>
151 >>>
151 >>>
152 """
152 """
153
153
154 def test_macro():
154 def test_macro():
155 ip = get_ipython()
155 ip = get_ipython()
156 ip.history_manager.reset() # Clear any existing history.
156 ip.history_manager.reset() # Clear any existing history.
157 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
157 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
158 for i, cmd in enumerate(cmds, start=1):
158 for i, cmd in enumerate(cmds, start=1):
159 ip.history_manager.store_inputs(i, cmd)
159 ip.history_manager.store_inputs(i, cmd)
160 ip.magic("macro test 1-3")
160 ip.magic("macro test 1-3")
161 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
161 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
162
162
163 # List macros.
163 # List macros.
164 assert "test" in ip.magic("macro")
164 assert "test" in ip.magic("macro")
165
165
166 def test_macro_run():
166 def test_macro_run():
167 """Test that we can run a multi-line macro successfully."""
167 """Test that we can run a multi-line macro successfully."""
168 ip = get_ipython()
168 ip = get_ipython()
169 ip.history_manager.reset()
169 ip.history_manager.reset()
170 cmds = ["a=10", "a+=1", "print a", "%macro test 2-3"]
170 cmds = ["a=10", "a+=1", "print a", "%macro test 2-3"]
171 for cmd in cmds:
171 for cmd in cmds:
172 ip.run_cell(cmd)
172 ip.run_cell(cmd)
173 nt.assert_equal(ip.user_ns["test"].value, "a+=1\nprint a\n")
173 nt.assert_equal(ip.user_ns["test"].value, "a+=1\nprint a\n")
174 original_stdout = sys.stdout
174 original_stdout = sys.stdout
175 new_stdout = StringIO()
175 new_stdout = StringIO()
176 sys.stdout = new_stdout
176 sys.stdout = new_stdout
177 try:
177 try:
178 ip.run_cell("test")
178 ip.run_cell("test")
179 nt.assert_true("12" in new_stdout.getvalue())
179 nt.assert_true("12" in new_stdout.getvalue())
180 ip.run_cell("test")
180 ip.run_cell("test")
181 nt.assert_true("13" in new_stdout.getvalue())
181 nt.assert_true("13" in new_stdout.getvalue())
182 finally:
182 finally:
183 sys.stdout = original_stdout
183 sys.stdout = original_stdout
184 new_stdout.close()
184 new_stdout.close()
185
185
186
186
187 # XXX failing for now, until we get clearcmd out of quarantine. But we should
187 # XXX failing for now, until we get clearcmd out of quarantine. But we should
188 # fix this and revert the skip to happen only if numpy is not around.
188 # fix this and revert the skip to happen only if numpy is not around.
189 #@dec.skipif_not_numpy
189 #@dec.skipif_not_numpy
190 @dec.skip_known_failure
190 @dec.skip_known_failure
191 def test_numpy_clear_array_undec():
191 def test_numpy_clear_array_undec():
192 from IPython.extensions import clearcmd
192 from IPython.extensions import clearcmd
193
193
194 _ip.ex('import numpy as np')
194 _ip.ex('import numpy as np')
195 _ip.ex('a = np.empty(2)')
195 _ip.ex('a = np.empty(2)')
196 yield (nt.assert_true, 'a' in _ip.user_ns)
196 yield (nt.assert_true, 'a' in _ip.user_ns)
197 _ip.magic('clear array')
197 _ip.magic('clear array')
198 yield (nt.assert_false, 'a' in _ip.user_ns)
198 yield (nt.assert_false, 'a' in _ip.user_ns)
199
199
200
200
201 # Multiple tests for clipboard pasting
201 # Multiple tests for clipboard pasting
202 @dec.parametric
202 @dec.parametric
203 def test_paste():
203 def test_paste():
204 _ip = get_ipython()
204 _ip = get_ipython()
205 def paste(txt, flags='-q'):
205 def paste(txt, flags='-q'):
206 """Paste input text, by default in quiet mode"""
206 """Paste input text, by default in quiet mode"""
207 hooks.clipboard_get = lambda : txt
207 hooks.clipboard_get = lambda : txt
208 _ip.magic('paste '+flags)
208 _ip.magic('paste '+flags)
209
209
210 # Inject fake clipboard hook but save original so we can restore it later
210 # Inject fake clipboard hook but save original so we can restore it later
211 hooks = _ip.hooks
211 hooks = _ip.hooks
212 user_ns = _ip.user_ns
212 user_ns = _ip.user_ns
213 original_clip = hooks.clipboard_get
213 original_clip = hooks.clipboard_get
214
214
215 try:
215 try:
216 # This try/except with an emtpy except clause is here only because
216 # This try/except with an emtpy except clause is here only because
217 # try/yield/finally is invalid syntax in Python 2.4. This will be
217 # try/yield/finally is invalid syntax in Python 2.4. This will be
218 # removed when we drop 2.4-compatibility, and the emtpy except below
218 # removed when we drop 2.4-compatibility, and the emtpy except below
219 # will be changed to a finally.
219 # will be changed to a finally.
220
220
221 # Run tests with fake clipboard function
221 # Run tests with fake clipboard function
222 user_ns.pop('x', None)
222 user_ns.pop('x', None)
223 paste('x=1')
223 paste('x=1')
224 yield nt.assert_equal(user_ns['x'], 1)
224 yield nt.assert_equal(user_ns['x'], 1)
225
225
226 user_ns.pop('x', None)
226 user_ns.pop('x', None)
227 paste('>>> x=2')
227 paste('>>> x=2')
228 yield nt.assert_equal(user_ns['x'], 2)
228 yield nt.assert_equal(user_ns['x'], 2)
229
229
230 paste("""
230 paste("""
231 >>> x = [1,2,3]
231 >>> x = [1,2,3]
232 >>> y = []
232 >>> y = []
233 >>> for i in x:
233 >>> for i in x:
234 ... y.append(i**2)
234 ... y.append(i**2)
235 ...
235 ...
236 """)
236 """)
237 yield nt.assert_equal(user_ns['x'], [1,2,3])
237 yield nt.assert_equal(user_ns['x'], [1,2,3])
238 yield nt.assert_equal(user_ns['y'], [1,4,9])
238 yield nt.assert_equal(user_ns['y'], [1,4,9])
239
239
240 # Now, test that paste -r works
240 # Now, test that paste -r works
241 user_ns.pop('x', None)
241 user_ns.pop('x', None)
242 yield nt.assert_false('x' in user_ns)
242 yield nt.assert_false('x' in user_ns)
243 _ip.magic('paste -r')
243 _ip.magic('paste -r')
244 yield nt.assert_equal(user_ns['x'], [1,2,3])
244 yield nt.assert_equal(user_ns['x'], [1,2,3])
245
245
246 # Also test paste echoing, by temporarily faking the writer
246 # Also test paste echoing, by temporarily faking the writer
247 w = StringIO()
247 w = StringIO()
248 writer = _ip.write
248 writer = _ip.write
249 _ip.write = w.write
249 _ip.write = w.write
250 code = """
250 code = """
251 a = 100
251 a = 100
252 b = 200"""
252 b = 200"""
253 try:
253 try:
254 paste(code,'')
254 paste(code,'')
255 out = w.getvalue()
255 out = w.getvalue()
256 finally:
256 finally:
257 _ip.write = writer
257 _ip.write = writer
258 yield nt.assert_equal(user_ns['a'], 100)
258 yield nt.assert_equal(user_ns['a'], 100)
259 yield nt.assert_equal(user_ns['b'], 200)
259 yield nt.assert_equal(user_ns['b'], 200)
260 yield nt.assert_equal(out, code+"\n## -- End pasted text --\n")
260 yield nt.assert_equal(out, code+"\n## -- End pasted text --\n")
261
261
262 finally:
262 finally:
263 # This should be in a finally clause, instead of the bare except above.
263 # This should be in a finally clause, instead of the bare except above.
264 # Restore original hook
264 # Restore original hook
265 hooks.clipboard_get = original_clip
265 hooks.clipboard_get = original_clip
266
266
267
267
268 def test_time():
268 def test_time():
269 _ip.magic('time None')
269 _ip.magic('time None')
270
270
271
271
272 def doctest_time():
272 def doctest_time():
273 """
273 """
274 In [10]: %time None
274 In [10]: %time None
275 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
275 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
276 Wall time: 0.00 s
276 Wall time: 0.00 s
277
277
278 In [11]: def f(kmjy):
278 In [11]: def f(kmjy):
279 ....: %time print 2*kmjy
279 ....: %time print 2*kmjy
280
280
281 In [12]: f(3)
281 In [12]: f(3)
282 6
282 6
283 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
283 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
284 Wall time: 0.00 s
284 Wall time: 0.00 s
285 """
285 """
286
286
287
287
288 def test_doctest_mode():
288 def test_doctest_mode():
289 "Toggle doctest_mode twice, it should be a no-op and run without error"
289 "Toggle doctest_mode twice, it should be a no-op and run without error"
290 _ip.magic('doctest_mode')
290 _ip.magic('doctest_mode')
291 _ip.magic('doctest_mode')
291 _ip.magic('doctest_mode')
292
292
293
293
294 def test_parse_options():
294 def test_parse_options():
295 """Tests for basic options parsing in magics."""
295 """Tests for basic options parsing in magics."""
296 # These are only the most minimal of tests, more should be added later. At
296 # These are only the most minimal of tests, more should be added later. At
297 # the very least we check that basic text/unicode calls work OK.
297 # the very least we check that basic text/unicode calls work OK.
298 nt.assert_equal(_ip.parse_options('foo', '')[1], 'foo')
298 nt.assert_equal(_ip.parse_options('foo', '')[1], 'foo')
299 nt.assert_equal(_ip.parse_options(u'foo', '')[1], u'foo')
299 nt.assert_equal(_ip.parse_options(u'foo', '')[1], u'foo')
300
300
301
301
302 def test_dirops():
302 def test_dirops():
303 """Test various directory handling operations."""
303 """Test various directory handling operations."""
304 curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
304 curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
305
305
306 startdir = os.getcwdu()
306 startdir = os.getcwdu()
307 ipdir = _ip.ipython_dir
307 ipdir = _ip.ipython_dir
308 try:
308 try:
309 _ip.magic('cd "%s"' % ipdir)
309 _ip.magic('cd "%s"' % ipdir)
310 nt.assert_equal(curpath(), ipdir)
310 nt.assert_equal(curpath(), ipdir)
311 _ip.magic('cd -')
311 _ip.magic('cd -')
312 nt.assert_equal(curpath(), startdir)
312 nt.assert_equal(curpath(), startdir)
313 _ip.magic('pushd "%s"' % ipdir)
313 _ip.magic('pushd "%s"' % ipdir)
314 nt.assert_equal(curpath(), ipdir)
314 nt.assert_equal(curpath(), ipdir)
315 _ip.magic('popd')
315 _ip.magic('popd')
316 nt.assert_equal(curpath(), startdir)
316 nt.assert_equal(curpath(), startdir)
317 finally:
317 finally:
318 os.chdir(startdir)
318 os.chdir(startdir)
319
319
320
320
321 def check_cpaste(code, should_fail=False):
321 def check_cpaste(code, should_fail=False):
322 """Execute code via 'cpaste' and ensure it was executed, unless
322 """Execute code via 'cpaste' and ensure it was executed, unless
323 should_fail is set.
323 should_fail is set.
324 """
324 """
325 _ip.user_ns['code_ran'] = False
325 _ip.user_ns['code_ran'] = False
326
326
327 src = StringIO()
327 src = StringIO()
328 src.write('\n')
328 src.write('\n')
329 src.write(code)
329 src.write(code)
330 src.write('\n--\n')
330 src.write('\n--\n')
331 src.seek(0)
331 src.seek(0)
332
332
333 stdin_save = sys.stdin
333 stdin_save = sys.stdin
334 sys.stdin = src
334 sys.stdin = src
335
335
336 try:
336 try:
337 _ip.magic('cpaste')
337 _ip.magic('cpaste')
338 except:
338 except:
339 if not should_fail:
339 if not should_fail:
340 raise AssertionError("Failure not expected : '%s'" %
340 raise AssertionError("Failure not expected : '%s'" %
341 code)
341 code)
342 else:
342 else:
343 assert _ip.user_ns['code_ran']
343 assert _ip.user_ns['code_ran']
344 if should_fail:
344 if should_fail:
345 raise AssertionError("Failure expected : '%s'" % code)
345 raise AssertionError("Failure expected : '%s'" % code)
346 finally:
346 finally:
347 sys.stdin = stdin_save
347 sys.stdin = stdin_save
348
348
349
349
350 def test_cpaste():
350 def test_cpaste():
351 """Test cpaste magic"""
351 """Test cpaste magic"""
352
352
353 def run():
353 def run():
354 """Marker function: sets a flag when executed.
354 """Marker function: sets a flag when executed.
355 """
355 """
356 _ip.user_ns['code_ran'] = True
356 _ip.user_ns['code_ran'] = True
357 return 'run' # return string so '+ run()' doesn't result in success
357 return 'run' # return string so '+ run()' doesn't result in success
358
358
359 tests = {'pass': ["> > > run()",
359 tests = {'pass': ["> > > run()",
360 ">>> > run()",
360 ">>> > run()",
361 "+++ run()",
361 "+++ run()",
362 "++ run()",
362 "++ run()",
363 " >>> run()"],
363 " >>> run()"],
364
364
365 'fail': ["+ + run()",
365 'fail': ["+ + run()",
366 " ++ run()"]}
366 " ++ run()"]}
367
367
368 _ip.user_ns['run'] = run
368 _ip.user_ns['run'] = run
369
369
370 for code in tests['pass']:
370 for code in tests['pass']:
371 check_cpaste(code)
371 check_cpaste(code)
372
372
373 for code in tests['fail']:
373 for code in tests['fail']:
374 check_cpaste(code, should_fail=True)
374 check_cpaste(code, should_fail=True)
375
375
376 def test_xmode():
376 def test_xmode():
377 # Calling xmode three times should be a no-op
377 # Calling xmode three times should be a no-op
378 xmode = _ip.InteractiveTB.mode
378 xmode = _ip.InteractiveTB.mode
379 for i in range(3):
379 for i in range(3):
380 _ip.magic("xmode")
380 _ip.magic("xmode")
381 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
381 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
382
382
383 def test_reset_hard():
383 def test_reset_hard():
384 monitor = []
384 monitor = []
385 class A(object):
385 class A(object):
386 def __del__(self):
386 def __del__(self):
387 monitor.append(1)
387 monitor.append(1)
388 def __repr__(self):
388 def __repr__(self):
389 return "<A instance>"
389 return "<A instance>"
390
390
391 _ip.user_ns["a"] = A()
391 _ip.user_ns["a"] = A()
392 _ip.run_cell("a")
392 _ip.run_cell("a")
393
393
394 nt.assert_equal(monitor, [])
394 nt.assert_equal(monitor, [])
395 _ip.magic_reset("-f")
395 _ip.magic_reset("-f")
396 nt.assert_equal(monitor, [1])
396 nt.assert_equal(monitor, [1])
397
397
398 class TestXdel(tt.TempFileMixin):
398 class TestXdel(tt.TempFileMixin):
399 def test_xdel(self):
399 def test_xdel(self):
400 """Test that references from %run are cleared by xdel."""
400 """Test that references from %run are cleared by xdel."""
401 src = ("class A(object):\n"
401 src = ("class A(object):\n"
402 " monitor = []\n"
402 " monitor = []\n"
403 " def __del__(self):\n"
403 " def __del__(self):\n"
404 " self.monitor.append(1)\n"
404 " self.monitor.append(1)\n"
405 "a = A()\n")
405 "a = A()\n")
406 self.mktmp(src)
406 self.mktmp(src)
407 # %run creates some hidden references...
407 _ip.magic("run %s" % self.fname)
408 _ip.magic("run %s" % self.fname)
409 # ... as does the displayhook.
408 _ip.run_cell("a")
410 _ip.run_cell("a")
411 a = _ip.user_ns["a"]
409 monitor = _ip.user_ns["A"].monitor
412 monitor = _ip.user_ns["A"].monitor
410 nt.assert_equal(monitor, [])
413 nt.assert_equal(monitor, [])
411 _ip.magic("xdel a")
414 _ip.magic("xdel a")
415
416 # The testing framework stores extra references - we kill those
417 # here. See IPython.testing.globalipapp.ipnsdict.
418 _ip.user_ns.killrefs(a)
419 del a
420
421 # For some reason the test doesn't pass if this is removed.
422 # TODO: Work out why, and improve the test.
423 f = sys._getframe()
424 print f.f_locals
425
426 # Check that a's __del__ method has been called.
412 nt.assert_equal(monitor, [1])
427 nt.assert_equal(monitor, [1])
413
428
414 def doctest_who():
429 def doctest_who():
415 """doctest for %who
430 """doctest for %who
416
431
417 In [1]: %reset -f
432 In [1]: %reset -f
418
433
419 In [2]: alpha = 123
434 In [2]: alpha = 123
420
435
421 In [3]: beta = 'beta'
436 In [3]: beta = 'beta'
422
437
423 In [4]: %who int
438 In [4]: %who int
424 alpha
439 alpha
425
440
426 In [5]: %who str
441 In [5]: %who str
427 beta
442 beta
428
443
429 In [6]: %whos
444 In [6]: %whos
430 Variable Type Data/Info
445 Variable Type Data/Info
431 ----------------------------
446 ----------------------------
432 alpha int 123
447 alpha int 123
433 beta str beta
448 beta str beta
434
449
435 In [7]: %who_ls
450 In [7]: %who_ls
436 Out[7]: ['alpha', 'beta']
451 Out[7]: ['alpha', 'beta']
437 """
452 """
438
453
439 def doctest_precision():
454 def doctest_precision():
440 """doctest for %precision
455 """doctest for %precision
441
456
442 In [1]: f = get_ipython().shell.display_formatter.formatters['text/plain']
457 In [1]: f = get_ipython().shell.display_formatter.formatters['text/plain']
443
458
444 In [2]: %precision 5
459 In [2]: %precision 5
445 Out[2]: '%.5f'
460 Out[2]: '%.5f'
446
461
447 In [3]: f.float_format
462 In [3]: f.float_format
448 Out[3]: '%.5f'
463 Out[3]: '%.5f'
449
464
450 In [4]: %precision %e
465 In [4]: %precision %e
451 Out[4]: '%e'
466 Out[4]: '%e'
452
467
453 In [5]: f(3.1415927)
468 In [5]: f(3.1415927)
454 Out[5]: '3.141593e+00'
469 Out[5]: '3.141593e+00'
455 """
470 """
456
471
@@ -1,220 +1,229 b''
1 """Global IPython app to support test running.
1 """Global IPython app to support test running.
2
2
3 We must start our own ipython object and heavily muck with it so that all the
3 We must start our own ipython object and heavily muck with it so that all the
4 modifications IPython makes to system behavior don't send the doctest machinery
4 modifications IPython makes to system behavior don't send the doctest machinery
5 into a fit. This code should be considered a gross hack, but it gets the job
5 into a fit. This code should be considered a gross hack, but it gets the job
6 done.
6 done.
7 """
7 """
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9 from __future__ import print_function
9 from __future__ import print_function
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2009-2010 The IPython Development Team
12 # Copyright (C) 2009-2010 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is in
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 # stdlib
22 # stdlib
23 import __builtin__
23 import __builtin__
24 import os
24 import os
25 import sys
25 import sys
26 from types import MethodType
26 from types import MethodType
27
27
28 # our own
28 # our own
29 from . import tools
29 from . import tools
30
30
31 from IPython.utils import io
31 from IPython.utils import io
32 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
32 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
33
33
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35 # Functions
35 # Functions
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37
37
38 class StreamProxy(io.IOStream):
38 class StreamProxy(io.IOStream):
39 """Proxy for sys.stdout/err. This will request the stream *at call time*
39 """Proxy for sys.stdout/err. This will request the stream *at call time*
40 allowing for nose's Capture plugin's redirection of sys.stdout/err.
40 allowing for nose's Capture plugin's redirection of sys.stdout/err.
41
41
42 Parameters
42 Parameters
43 ----------
43 ----------
44 name : str
44 name : str
45 The name of the stream. This will be requested anew at every call
45 The name of the stream. This will be requested anew at every call
46 """
46 """
47
47
48 def __init__(self, name):
48 def __init__(self, name):
49 self.name=name
49 self.name=name
50
50
51 @property
51 @property
52 def stream(self):
52 def stream(self):
53 return getattr(sys, self.name)
53 return getattr(sys, self.name)
54
54
55 def flush(self):
55 def flush(self):
56 self.stream.flush()
56 self.stream.flush()
57
57
58 # Hack to modify the %run command so we can sync the user's namespace with the
58 # Hack to modify the %run command so we can sync the user's namespace with the
59 # test globals. Once we move over to a clean magic system, this will be done
59 # test globals. Once we move over to a clean magic system, this will be done
60 # with much less ugliness.
60 # with much less ugliness.
61
61
62 class py_file_finder(object):
62 class py_file_finder(object):
63 def __init__(self,test_filename):
63 def __init__(self,test_filename):
64 self.test_filename = test_filename
64 self.test_filename = test_filename
65
65
66 def __call__(self,name):
66 def __call__(self,name):
67 from IPython.utils.path import get_py_filename
67 from IPython.utils.path import get_py_filename
68 try:
68 try:
69 return get_py_filename(name)
69 return get_py_filename(name)
70 except IOError:
70 except IOError:
71 test_dir = os.path.dirname(self.test_filename)
71 test_dir = os.path.dirname(self.test_filename)
72 new_path = os.path.join(test_dir,name)
72 new_path = os.path.join(test_dir,name)
73 return get_py_filename(new_path)
73 return get_py_filename(new_path)
74
74
75
75
76 def _run_ns_sync(self,arg_s,runner=None):
76 def _run_ns_sync(self,arg_s,runner=None):
77 """Modified version of %run that syncs testing namespaces.
77 """Modified version of %run that syncs testing namespaces.
78
78
79 This is strictly needed for running doctests that call %run.
79 This is strictly needed for running doctests that call %run.
80 """
80 """
81 #print('in run_ns_sync', arg_s, file=sys.stderr) # dbg
81 #print('in run_ns_sync', arg_s, file=sys.stderr) # dbg
82 finder = py_file_finder(arg_s)
82 finder = py_file_finder(arg_s)
83 return get_ipython().magic_run_ori(arg_s, runner, finder)
83 return get_ipython().magic_run_ori(arg_s, runner, finder)
84
84
85
85
86 class ipnsdict(dict):
86 class ipnsdict(dict):
87 """A special subclass of dict for use as an IPython namespace in doctests.
87 """A special subclass of dict for use as an IPython namespace in doctests.
88
88
89 This subclass adds a simple checkpointing capability so that when testing
89 This subclass adds a simple checkpointing capability so that when testing
90 machinery clears it (we use it as the test execution context), it doesn't
90 machinery clears it (we use it as the test execution context), it doesn't
91 get completely destroyed.
91 get completely destroyed.
92
92
93 In addition, it can handle the presence of the '_' key in a special manner,
93 In addition, it can handle the presence of the '_' key in a special manner,
94 which is needed because of how Python's doctest machinery operates with
94 which is needed because of how Python's doctest machinery operates with
95 '_'. See constructor and :meth:`update` for details.
95 '_'. See constructor and :meth:`update` for details.
96 """
96 """
97
97
98 def __init__(self,*a):
98 def __init__(self,*a):
99 dict.__init__(self,*a)
99 dict.__init__(self,*a)
100 self._savedict = {}
100 self._savedict = {}
101 # If this flag is True, the .update() method will unconditionally
101 # If this flag is True, the .update() method will unconditionally
102 # remove a key named '_'. This is so that such a dict can be used as a
102 # remove a key named '_'. This is so that such a dict can be used as a
103 # namespace in doctests that call '_'.
103 # namespace in doctests that call '_'.
104 self.protect_underscore = False
104 self.protect_underscore = False
105
105
106 def clear(self):
106 def clear(self):
107 dict.clear(self)
107 dict.clear(self)
108 self.update(self._savedict)
108 self.update(self._savedict)
109
109
110 def _checkpoint(self):
110 def _checkpoint(self):
111 self._savedict.clear()
111 self._savedict.clear()
112 self._savedict.update(self)
112 self._savedict.update(self)
113
113
114 def update(self,other):
114 def update(self,other):
115 self._checkpoint()
115 self._checkpoint()
116 dict.update(self,other)
116 dict.update(self,other)
117
117
118 if self.protect_underscore:
118 if self.protect_underscore:
119 # If '_' is in the namespace, python won't set it when executing
119 # If '_' is in the namespace, python won't set it when executing
120 # code *in doctests*, and we have multiple doctests that use '_'.
120 # code *in doctests*, and we have multiple doctests that use '_'.
121 # So we ensure that the namespace is always 'clean' of it before
121 # So we ensure that the namespace is always 'clean' of it before
122 # it's used for test code execution.
122 # it's used for test code execution.
123 # This flag is only turned on by the doctest machinery, so that
123 # This flag is only turned on by the doctest machinery, so that
124 # normal test code can assume the _ key is updated like any other
124 # normal test code can assume the _ key is updated like any other
125 # key and can test for its presence after cell executions.
125 # key and can test for its presence after cell executions.
126 self.pop('_', None)
126 self.pop('_', None)
127
127
128 # The builtins namespace must *always* be the real __builtin__ module,
128 # The builtins namespace must *always* be the real __builtin__ module,
129 # else weird stuff happens. The main ipython code does have provisions
129 # else weird stuff happens. The main ipython code does have provisions
130 # to ensure this after %run, but since in this class we do some
130 # to ensure this after %run, but since in this class we do some
131 # aggressive low-level cleaning of the execution namespace, we need to
131 # aggressive low-level cleaning of the execution namespace, we need to
132 # correct for that ourselves, to ensure consitency with the 'real'
132 # correct for that ourselves, to ensure consitency with the 'real'
133 # ipython.
133 # ipython.
134 self['__builtins__'] = __builtin__
134 self['__builtins__'] = __builtin__
135
136 def killrefs(self, obj):
137 """For part of the testing, we need to be able to remove
138 references to an object, which would otherwise be kept in
139 _savedict."""
140 todel = [n for n, o in self._savedict.iteritems() if o is obj]
141 for n in todel:
142 del self._savedict[n]
143
135
144
136
145
137 def get_ipython():
146 def get_ipython():
138 # This will get replaced by the real thing once we start IPython below
147 # This will get replaced by the real thing once we start IPython below
139 return start_ipython()
148 return start_ipython()
140
149
141
150
142 # A couple of methods to override those in the running IPython to interact
151 # A couple of methods to override those in the running IPython to interact
143 # better with doctest (doctest captures on raw stdout, so we need to direct
152 # better with doctest (doctest captures on raw stdout, so we need to direct
144 # various types of output there otherwise it will miss them).
153 # various types of output there otherwise it will miss them).
145
154
146 def xsys(self, cmd):
155 def xsys(self, cmd):
147 """Replace the default system call with a capturing one for doctest.
156 """Replace the default system call with a capturing one for doctest.
148 """
157 """
149 # We use getoutput, but we need to strip it because pexpect captures
158 # We use getoutput, but we need to strip it because pexpect captures
150 # the trailing newline differently from commands.getoutput
159 # the trailing newline differently from commands.getoutput
151 print(self.getoutput(cmd, split=False).rstrip(), end='', file=sys.stdout)
160 print(self.getoutput(cmd, split=False).rstrip(), end='', file=sys.stdout)
152 sys.stdout.flush()
161 sys.stdout.flush()
153
162
154
163
155 def _showtraceback(self, etype, evalue, stb):
164 def _showtraceback(self, etype, evalue, stb):
156 """Print the traceback purely on stdout for doctest to capture it.
165 """Print the traceback purely on stdout for doctest to capture it.
157 """
166 """
158 print(self.InteractiveTB.stb2text(stb), file=sys.stdout)
167 print(self.InteractiveTB.stb2text(stb), file=sys.stdout)
159
168
160
169
161 def start_ipython():
170 def start_ipython():
162 """Start a global IPython shell, which we need for IPython-specific syntax.
171 """Start a global IPython shell, which we need for IPython-specific syntax.
163 """
172 """
164 global get_ipython
173 global get_ipython
165
174
166 # This function should only ever run once!
175 # This function should only ever run once!
167 if hasattr(start_ipython, 'already_called'):
176 if hasattr(start_ipython, 'already_called'):
168 return
177 return
169 start_ipython.already_called = True
178 start_ipython.already_called = True
170
179
171 # Store certain global objects that IPython modifies
180 # Store certain global objects that IPython modifies
172 _displayhook = sys.displayhook
181 _displayhook = sys.displayhook
173 _excepthook = sys.excepthook
182 _excepthook = sys.excepthook
174 _main = sys.modules.get('__main__')
183 _main = sys.modules.get('__main__')
175
184
176 # Create custom argv and namespaces for our IPython to be test-friendly
185 # Create custom argv and namespaces for our IPython to be test-friendly
177 config = tools.default_config()
186 config = tools.default_config()
178
187
179 # Create and initialize our test-friendly IPython instance.
188 # Create and initialize our test-friendly IPython instance.
180 shell = TerminalInteractiveShell.instance(config=config,
189 shell = TerminalInteractiveShell.instance(config=config,
181 user_ns=ipnsdict(),
190 user_ns=ipnsdict(),
182 user_global_ns={}
191 user_global_ns={}
183 )
192 )
184
193
185 # A few more tweaks needed for playing nicely with doctests...
194 # A few more tweaks needed for playing nicely with doctests...
186
195
187 # These traps are normally only active for interactive use, set them
196 # These traps are normally only active for interactive use, set them
188 # permanently since we'll be mocking interactive sessions.
197 # permanently since we'll be mocking interactive sessions.
189 shell.builtin_trap.activate()
198 shell.builtin_trap.activate()
190
199
191 # Modify the IPython system call with one that uses getoutput, so that we
200 # Modify the IPython system call with one that uses getoutput, so that we
192 # can capture subcommands and print them to Python's stdout, otherwise the
201 # can capture subcommands and print them to Python's stdout, otherwise the
193 # doctest machinery would miss them.
202 # doctest machinery would miss them.
194 shell.system = MethodType(xsys, shell, TerminalInteractiveShell)
203 shell.system = MethodType(xsys, shell, TerminalInteractiveShell)
195
204
196
205
197 shell._showtraceback = MethodType(_showtraceback, shell,
206 shell._showtraceback = MethodType(_showtraceback, shell,
198 TerminalInteractiveShell)
207 TerminalInteractiveShell)
199
208
200 # IPython is ready, now clean up some global state...
209 # IPython is ready, now clean up some global state...
201
210
202 # Deactivate the various python system hooks added by ipython for
211 # Deactivate the various python system hooks added by ipython for
203 # interactive convenience so we don't confuse the doctest system
212 # interactive convenience so we don't confuse the doctest system
204 sys.modules['__main__'] = _main
213 sys.modules['__main__'] = _main
205 sys.displayhook = _displayhook
214 sys.displayhook = _displayhook
206 sys.excepthook = _excepthook
215 sys.excepthook = _excepthook
207
216
208 # So that ipython magics and aliases can be doctested (they work by making
217 # So that ipython magics and aliases can be doctested (they work by making
209 # a call into a global _ip object). Also make the top-level get_ipython
218 # a call into a global _ip object). Also make the top-level get_ipython
210 # now return this without recursively calling here again.
219 # now return this without recursively calling here again.
211 _ip = shell
220 _ip = shell
212 get_ipython = _ip.get_ipython
221 get_ipython = _ip.get_ipython
213 __builtin__._ip = _ip
222 __builtin__._ip = _ip
214 __builtin__.get_ipython = get_ipython
223 __builtin__.get_ipython = get_ipython
215
224
216 # To avoid extra IPython messages during testing, suppress io.stdout/stderr
225 # To avoid extra IPython messages during testing, suppress io.stdout/stderr
217 io.stdout = StreamProxy('stdout')
226 io.stdout = StreamProxy('stdout')
218 io.stderr = StreamProxy('stderr')
227 io.stderr = StreamProxy('stderr')
219
228
220 return _ip
229 return _ip
General Comments 0
You need to be logged in to leave comments. Login now