##// END OF EJS Templates
Add test for _exit_code from system_raw.
Thomas Kluyver -
Show More
@@ -1,559 +1,564 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for the key interactiveshell module.
2 """Tests for the key interactiveshell module.
3
3
4 Historically the main classes in interactiveshell have been under-tested. This
4 Historically the main classes in interactiveshell have been under-tested. This
5 module should grow as many single-method tests as possible to trap many of the
5 module should grow as many single-method tests as possible to trap many of the
6 recurring bugs we seem to encounter with high-level interaction.
6 recurring bugs we seem to encounter with high-level interaction.
7
7
8 Authors
8 Authors
9 -------
9 -------
10 * Fernando Perez
10 * Fernando Perez
11 """
11 """
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2011 The IPython Development Team
13 # Copyright (C) 2011 The IPython Development Team
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # stdlib
22 # stdlib
23 import ast
23 import ast
24 import os
24 import os
25 import shutil
25 import shutil
26 import sys
26 import sys
27 import tempfile
27 import tempfile
28 import unittest
28 import unittest
29 from os.path import join
29 from os.path import join
30 from StringIO import StringIO
30 from StringIO import StringIO
31
31
32 # third-party
32 # third-party
33 import nose.tools as nt
33 import nose.tools as nt
34
34
35 # Our own
35 # Our own
36 from IPython.testing.decorators import skipif
36 from IPython.testing.decorators import skipif
37 from IPython.testing import tools as tt
37 from IPython.testing import tools as tt
38 from IPython.utils import io
38 from IPython.utils import io
39
39
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 # Globals
41 # Globals
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43 # This is used by every single test, no point repeating it ad nauseam
43 # This is used by every single test, no point repeating it ad nauseam
44 ip = get_ipython()
44 ip = get_ipython()
45
45
46 #-----------------------------------------------------------------------------
46 #-----------------------------------------------------------------------------
47 # Tests
47 # Tests
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49
49
50 class InteractiveShellTestCase(unittest.TestCase):
50 class InteractiveShellTestCase(unittest.TestCase):
51 def test_naked_string_cells(self):
51 def test_naked_string_cells(self):
52 """Test that cells with only naked strings are fully executed"""
52 """Test that cells with only naked strings are fully executed"""
53 # First, single-line inputs
53 # First, single-line inputs
54 ip.run_cell('"a"\n')
54 ip.run_cell('"a"\n')
55 self.assertEqual(ip.user_ns['_'], 'a')
55 self.assertEqual(ip.user_ns['_'], 'a')
56 # And also multi-line cells
56 # And also multi-line cells
57 ip.run_cell('"""a\nb"""\n')
57 ip.run_cell('"""a\nb"""\n')
58 self.assertEqual(ip.user_ns['_'], 'a\nb')
58 self.assertEqual(ip.user_ns['_'], 'a\nb')
59
59
60 def test_run_empty_cell(self):
60 def test_run_empty_cell(self):
61 """Just make sure we don't get a horrible error with a blank
61 """Just make sure we don't get a horrible error with a blank
62 cell of input. Yes, I did overlook that."""
62 cell of input. Yes, I did overlook that."""
63 old_xc = ip.execution_count
63 old_xc = ip.execution_count
64 ip.run_cell('')
64 ip.run_cell('')
65 self.assertEqual(ip.execution_count, old_xc)
65 self.assertEqual(ip.execution_count, old_xc)
66
66
67 def test_run_cell_multiline(self):
67 def test_run_cell_multiline(self):
68 """Multi-block, multi-line cells must execute correctly.
68 """Multi-block, multi-line cells must execute correctly.
69 """
69 """
70 src = '\n'.join(["x=1",
70 src = '\n'.join(["x=1",
71 "y=2",
71 "y=2",
72 "if 1:",
72 "if 1:",
73 " x += 1",
73 " x += 1",
74 " y += 1",])
74 " y += 1",])
75 ip.run_cell(src)
75 ip.run_cell(src)
76 self.assertEqual(ip.user_ns['x'], 2)
76 self.assertEqual(ip.user_ns['x'], 2)
77 self.assertEqual(ip.user_ns['y'], 3)
77 self.assertEqual(ip.user_ns['y'], 3)
78
78
79 def test_multiline_string_cells(self):
79 def test_multiline_string_cells(self):
80 "Code sprinkled with multiline strings should execute (GH-306)"
80 "Code sprinkled with multiline strings should execute (GH-306)"
81 ip.run_cell('tmp=0')
81 ip.run_cell('tmp=0')
82 self.assertEqual(ip.user_ns['tmp'], 0)
82 self.assertEqual(ip.user_ns['tmp'], 0)
83 ip.run_cell('tmp=1;"""a\nb"""\n')
83 ip.run_cell('tmp=1;"""a\nb"""\n')
84 self.assertEqual(ip.user_ns['tmp'], 1)
84 self.assertEqual(ip.user_ns['tmp'], 1)
85
85
86 def test_dont_cache_with_semicolon(self):
86 def test_dont_cache_with_semicolon(self):
87 "Ending a line with semicolon should not cache the returned object (GH-307)"
87 "Ending a line with semicolon should not cache the returned object (GH-307)"
88 oldlen = len(ip.user_ns['Out'])
88 oldlen = len(ip.user_ns['Out'])
89 a = ip.run_cell('1;', store_history=True)
89 a = ip.run_cell('1;', store_history=True)
90 newlen = len(ip.user_ns['Out'])
90 newlen = len(ip.user_ns['Out'])
91 self.assertEqual(oldlen, newlen)
91 self.assertEqual(oldlen, newlen)
92 #also test the default caching behavior
92 #also test the default caching behavior
93 ip.run_cell('1', store_history=True)
93 ip.run_cell('1', store_history=True)
94 newlen = len(ip.user_ns['Out'])
94 newlen = len(ip.user_ns['Out'])
95 self.assertEqual(oldlen+1, newlen)
95 self.assertEqual(oldlen+1, newlen)
96
96
97 def test_In_variable(self):
97 def test_In_variable(self):
98 "Verify that In variable grows with user input (GH-284)"
98 "Verify that In variable grows with user input (GH-284)"
99 oldlen = len(ip.user_ns['In'])
99 oldlen = len(ip.user_ns['In'])
100 ip.run_cell('1;', store_history=True)
100 ip.run_cell('1;', store_history=True)
101 newlen = len(ip.user_ns['In'])
101 newlen = len(ip.user_ns['In'])
102 self.assertEqual(oldlen+1, newlen)
102 self.assertEqual(oldlen+1, newlen)
103 self.assertEqual(ip.user_ns['In'][-1],'1;')
103 self.assertEqual(ip.user_ns['In'][-1],'1;')
104
104
105 def test_magic_names_in_string(self):
105 def test_magic_names_in_string(self):
106 ip.run_cell('a = """\n%exit\n"""')
106 ip.run_cell('a = """\n%exit\n"""')
107 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
107 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
108
108
109 def test_alias_crash(self):
109 def test_alias_crash(self):
110 """Errors in prefilter can't crash IPython"""
110 """Errors in prefilter can't crash IPython"""
111 ip.run_cell('%alias parts echo first %s second %s')
111 ip.run_cell('%alias parts echo first %s second %s')
112 # capture stderr:
112 # capture stderr:
113 save_err = io.stderr
113 save_err = io.stderr
114 io.stderr = StringIO()
114 io.stderr = StringIO()
115 ip.run_cell('parts 1')
115 ip.run_cell('parts 1')
116 err = io.stderr.getvalue()
116 err = io.stderr.getvalue()
117 io.stderr = save_err
117 io.stderr = save_err
118 self.assertEqual(err.split(':')[0], 'ERROR')
118 self.assertEqual(err.split(':')[0], 'ERROR')
119
119
120 def test_trailing_newline(self):
120 def test_trailing_newline(self):
121 """test that running !(command) does not raise a SyntaxError"""
121 """test that running !(command) does not raise a SyntaxError"""
122 ip.run_cell('!(true)\n', False)
122 ip.run_cell('!(true)\n', False)
123 ip.run_cell('!(true)\n\n\n', False)
123 ip.run_cell('!(true)\n\n\n', False)
124
124
125 def test_gh_597(self):
125 def test_gh_597(self):
126 """Pretty-printing lists of objects with non-ascii reprs may cause
126 """Pretty-printing lists of objects with non-ascii reprs may cause
127 problems."""
127 problems."""
128 class Spam(object):
128 class Spam(object):
129 def __repr__(self):
129 def __repr__(self):
130 return "\xe9"*50
130 return "\xe9"*50
131 import IPython.core.formatters
131 import IPython.core.formatters
132 f = IPython.core.formatters.PlainTextFormatter()
132 f = IPython.core.formatters.PlainTextFormatter()
133 f([Spam(),Spam()])
133 f([Spam(),Spam()])
134
134
135
135
136 def test_future_flags(self):
136 def test_future_flags(self):
137 """Check that future flags are used for parsing code (gh-777)"""
137 """Check that future flags are used for parsing code (gh-777)"""
138 ip.run_cell('from __future__ import print_function')
138 ip.run_cell('from __future__ import print_function')
139 try:
139 try:
140 ip.run_cell('prfunc_return_val = print(1,2, sep=" ")')
140 ip.run_cell('prfunc_return_val = print(1,2, sep=" ")')
141 assert 'prfunc_return_val' in ip.user_ns
141 assert 'prfunc_return_val' in ip.user_ns
142 finally:
142 finally:
143 # Reset compiler flags so we don't mess up other tests.
143 # Reset compiler flags so we don't mess up other tests.
144 ip.compile.reset_compiler_flags()
144 ip.compile.reset_compiler_flags()
145
145
146 def test_future_unicode(self):
146 def test_future_unicode(self):
147 """Check that unicode_literals is imported from __future__ (gh #786)"""
147 """Check that unicode_literals is imported from __future__ (gh #786)"""
148 try:
148 try:
149 ip.run_cell(u'byte_str = "a"')
149 ip.run_cell(u'byte_str = "a"')
150 assert isinstance(ip.user_ns['byte_str'], str) # string literals are byte strings by default
150 assert isinstance(ip.user_ns['byte_str'], str) # string literals are byte strings by default
151 ip.run_cell('from __future__ import unicode_literals')
151 ip.run_cell('from __future__ import unicode_literals')
152 ip.run_cell(u'unicode_str = "a"')
152 ip.run_cell(u'unicode_str = "a"')
153 assert isinstance(ip.user_ns['unicode_str'], unicode) # strings literals are now unicode
153 assert isinstance(ip.user_ns['unicode_str'], unicode) # strings literals are now unicode
154 finally:
154 finally:
155 # Reset compiler flags so we don't mess up other tests.
155 # Reset compiler flags so we don't mess up other tests.
156 ip.compile.reset_compiler_flags()
156 ip.compile.reset_compiler_flags()
157
157
158 def test_can_pickle(self):
158 def test_can_pickle(self):
159 "Can we pickle objects defined interactively (GH-29)"
159 "Can we pickle objects defined interactively (GH-29)"
160 ip = get_ipython()
160 ip = get_ipython()
161 ip.reset()
161 ip.reset()
162 ip.run_cell(("class Mylist(list):\n"
162 ip.run_cell(("class Mylist(list):\n"
163 " def __init__(self,x=[]):\n"
163 " def __init__(self,x=[]):\n"
164 " list.__init__(self,x)"))
164 " list.__init__(self,x)"))
165 ip.run_cell("w=Mylist([1,2,3])")
165 ip.run_cell("w=Mylist([1,2,3])")
166
166
167 from cPickle import dumps
167 from cPickle import dumps
168
168
169 # We need to swap in our main module - this is only necessary
169 # We need to swap in our main module - this is only necessary
170 # inside the test framework, because IPython puts the interactive module
170 # inside the test framework, because IPython puts the interactive module
171 # in place (but the test framework undoes this).
171 # in place (but the test framework undoes this).
172 _main = sys.modules['__main__']
172 _main = sys.modules['__main__']
173 sys.modules['__main__'] = ip.user_module
173 sys.modules['__main__'] = ip.user_module
174 try:
174 try:
175 res = dumps(ip.user_ns["w"])
175 res = dumps(ip.user_ns["w"])
176 finally:
176 finally:
177 sys.modules['__main__'] = _main
177 sys.modules['__main__'] = _main
178 self.assertTrue(isinstance(res, bytes))
178 self.assertTrue(isinstance(res, bytes))
179
179
180 def test_global_ns(self):
180 def test_global_ns(self):
181 "Code in functions must be able to access variables outside them."
181 "Code in functions must be able to access variables outside them."
182 ip = get_ipython()
182 ip = get_ipython()
183 ip.run_cell("a = 10")
183 ip.run_cell("a = 10")
184 ip.run_cell(("def f(x):\n"
184 ip.run_cell(("def f(x):\n"
185 " return x + a"))
185 " return x + a"))
186 ip.run_cell("b = f(12)")
186 ip.run_cell("b = f(12)")
187 self.assertEqual(ip.user_ns["b"], 22)
187 self.assertEqual(ip.user_ns["b"], 22)
188
188
189 def test_bad_custom_tb(self):
189 def test_bad_custom_tb(self):
190 """Check that InteractiveShell is protected from bad custom exception handlers"""
190 """Check that InteractiveShell is protected from bad custom exception handlers"""
191 from IPython.utils import io
191 from IPython.utils import io
192 save_stderr = io.stderr
192 save_stderr = io.stderr
193 try:
193 try:
194 # capture stderr
194 # capture stderr
195 io.stderr = StringIO()
195 io.stderr = StringIO()
196 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
196 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
197 self.assertEqual(ip.custom_exceptions, (IOError,))
197 self.assertEqual(ip.custom_exceptions, (IOError,))
198 ip.run_cell(u'raise IOError("foo")')
198 ip.run_cell(u'raise IOError("foo")')
199 self.assertEqual(ip.custom_exceptions, ())
199 self.assertEqual(ip.custom_exceptions, ())
200 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
200 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
201 finally:
201 finally:
202 io.stderr = save_stderr
202 io.stderr = save_stderr
203
203
204 def test_bad_custom_tb_return(self):
204 def test_bad_custom_tb_return(self):
205 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
205 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
206 from IPython.utils import io
206 from IPython.utils import io
207 save_stderr = io.stderr
207 save_stderr = io.stderr
208 try:
208 try:
209 # capture stderr
209 # capture stderr
210 io.stderr = StringIO()
210 io.stderr = StringIO()
211 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
211 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
212 self.assertEqual(ip.custom_exceptions, (NameError,))
212 self.assertEqual(ip.custom_exceptions, (NameError,))
213 ip.run_cell(u'a=abracadabra')
213 ip.run_cell(u'a=abracadabra')
214 self.assertEqual(ip.custom_exceptions, ())
214 self.assertEqual(ip.custom_exceptions, ())
215 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
215 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
216 finally:
216 finally:
217 io.stderr = save_stderr
217 io.stderr = save_stderr
218
218
219 def test_drop_by_id(self):
219 def test_drop_by_id(self):
220 myvars = {"a":object(), "b":object(), "c": object()}
220 myvars = {"a":object(), "b":object(), "c": object()}
221 ip.push(myvars, interactive=False)
221 ip.push(myvars, interactive=False)
222 for name in myvars:
222 for name in myvars:
223 assert name in ip.user_ns, name
223 assert name in ip.user_ns, name
224 assert name in ip.user_ns_hidden, name
224 assert name in ip.user_ns_hidden, name
225 ip.user_ns['b'] = 12
225 ip.user_ns['b'] = 12
226 ip.drop_by_id(myvars)
226 ip.drop_by_id(myvars)
227 for name in ["a", "c"]:
227 for name in ["a", "c"]:
228 assert name not in ip.user_ns, name
228 assert name not in ip.user_ns, name
229 assert name not in ip.user_ns_hidden, name
229 assert name not in ip.user_ns_hidden, name
230 assert ip.user_ns['b'] == 12
230 assert ip.user_ns['b'] == 12
231 ip.reset()
231 ip.reset()
232
232
233 def test_var_expand(self):
233 def test_var_expand(self):
234 ip.user_ns['f'] = u'Ca\xf1o'
234 ip.user_ns['f'] = u'Ca\xf1o'
235 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
235 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
236 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
236 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
237 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
237 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
238 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
238 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
239
239
240 ip.user_ns['f'] = b'Ca\xc3\xb1o'
240 ip.user_ns['f'] = b'Ca\xc3\xb1o'
241 # This should not raise any exception:
241 # This should not raise any exception:
242 ip.var_expand(u'echo $f')
242 ip.var_expand(u'echo $f')
243
243
244 def test_var_expand_local(self):
244 def test_var_expand_local(self):
245 """Test local variable expansion in !system and %magic calls"""
245 """Test local variable expansion in !system and %magic calls"""
246 # !system
246 # !system
247 ip.run_cell('def test():\n'
247 ip.run_cell('def test():\n'
248 ' lvar = "ttt"\n'
248 ' lvar = "ttt"\n'
249 ' ret = !echo {lvar}\n'
249 ' ret = !echo {lvar}\n'
250 ' return ret[0]\n')
250 ' return ret[0]\n')
251 res = ip.user_ns['test']()
251 res = ip.user_ns['test']()
252 nt.assert_in('ttt', res)
252 nt.assert_in('ttt', res)
253
253
254 # %magic
254 # %magic
255 ip.run_cell('def makemacro():\n'
255 ip.run_cell('def makemacro():\n'
256 ' macroname = "macro_var_expand_locals"\n'
256 ' macroname = "macro_var_expand_locals"\n'
257 ' %macro {macroname} codestr\n')
257 ' %macro {macroname} codestr\n')
258 ip.user_ns['codestr'] = "str(12)"
258 ip.user_ns['codestr'] = "str(12)"
259 ip.run_cell('makemacro()')
259 ip.run_cell('makemacro()')
260 nt.assert_in('macro_var_expand_locals', ip.user_ns)
260 nt.assert_in('macro_var_expand_locals', ip.user_ns)
261
261
262 def test_var_expand_self(self):
262 def test_var_expand_self(self):
263 """Test variable expansion with the name 'self', which was failing.
263 """Test variable expansion with the name 'self', which was failing.
264
264
265 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
265 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
266 """
266 """
267 ip.run_cell('class cTest:\n'
267 ip.run_cell('class cTest:\n'
268 ' classvar="see me"\n'
268 ' classvar="see me"\n'
269 ' def test(self):\n'
269 ' def test(self):\n'
270 ' res = !echo Variable: {self.classvar}\n'
270 ' res = !echo Variable: {self.classvar}\n'
271 ' return res[0]\n')
271 ' return res[0]\n')
272 nt.assert_in('see me', ip.user_ns['cTest']().test())
272 nt.assert_in('see me', ip.user_ns['cTest']().test())
273
273
274 def test_bad_var_expand(self):
274 def test_bad_var_expand(self):
275 """var_expand on invalid formats shouldn't raise"""
275 """var_expand on invalid formats shouldn't raise"""
276 # SyntaxError
276 # SyntaxError
277 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
277 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
278 # NameError
278 # NameError
279 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
279 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
280 # ZeroDivisionError
280 # ZeroDivisionError
281 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
281 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
282
282
283 def test_silent_nopostexec(self):
283 def test_silent_nopostexec(self):
284 """run_cell(silent=True) doesn't invoke post-exec funcs"""
284 """run_cell(silent=True) doesn't invoke post-exec funcs"""
285 d = dict(called=False)
285 d = dict(called=False)
286 def set_called():
286 def set_called():
287 d['called'] = True
287 d['called'] = True
288
288
289 ip.register_post_execute(set_called)
289 ip.register_post_execute(set_called)
290 ip.run_cell("1", silent=True)
290 ip.run_cell("1", silent=True)
291 self.assertFalse(d['called'])
291 self.assertFalse(d['called'])
292 # double-check that non-silent exec did what we expected
292 # double-check that non-silent exec did what we expected
293 # silent to avoid
293 # silent to avoid
294 ip.run_cell("1")
294 ip.run_cell("1")
295 self.assertTrue(d['called'])
295 self.assertTrue(d['called'])
296 # remove post-exec
296 # remove post-exec
297 ip._post_execute.pop(set_called)
297 ip._post_execute.pop(set_called)
298
298
299 def test_silent_noadvance(self):
299 def test_silent_noadvance(self):
300 """run_cell(silent=True) doesn't advance execution_count"""
300 """run_cell(silent=True) doesn't advance execution_count"""
301 ec = ip.execution_count
301 ec = ip.execution_count
302 # silent should force store_history=False
302 # silent should force store_history=False
303 ip.run_cell("1", store_history=True, silent=True)
303 ip.run_cell("1", store_history=True, silent=True)
304
304
305 self.assertEqual(ec, ip.execution_count)
305 self.assertEqual(ec, ip.execution_count)
306 # double-check that non-silent exec did what we expected
306 # double-check that non-silent exec did what we expected
307 # silent to avoid
307 # silent to avoid
308 ip.run_cell("1", store_history=True)
308 ip.run_cell("1", store_history=True)
309 self.assertEqual(ec+1, ip.execution_count)
309 self.assertEqual(ec+1, ip.execution_count)
310
310
311 def test_silent_nodisplayhook(self):
311 def test_silent_nodisplayhook(self):
312 """run_cell(silent=True) doesn't trigger displayhook"""
312 """run_cell(silent=True) doesn't trigger displayhook"""
313 d = dict(called=False)
313 d = dict(called=False)
314
314
315 trap = ip.display_trap
315 trap = ip.display_trap
316 save_hook = trap.hook
316 save_hook = trap.hook
317
317
318 def failing_hook(*args, **kwargs):
318 def failing_hook(*args, **kwargs):
319 d['called'] = True
319 d['called'] = True
320
320
321 try:
321 try:
322 trap.hook = failing_hook
322 trap.hook = failing_hook
323 ip.run_cell("1", silent=True)
323 ip.run_cell("1", silent=True)
324 self.assertFalse(d['called'])
324 self.assertFalse(d['called'])
325 # double-check that non-silent exec did what we expected
325 # double-check that non-silent exec did what we expected
326 # silent to avoid
326 # silent to avoid
327 ip.run_cell("1")
327 ip.run_cell("1")
328 self.assertTrue(d['called'])
328 self.assertTrue(d['called'])
329 finally:
329 finally:
330 trap.hook = save_hook
330 trap.hook = save_hook
331
331
332 @skipif(sys.version_info[0] >= 3, "softspace removed in py3")
332 @skipif(sys.version_info[0] >= 3, "softspace removed in py3")
333 def test_print_softspace(self):
333 def test_print_softspace(self):
334 """Verify that softspace is handled correctly when executing multiple
334 """Verify that softspace is handled correctly when executing multiple
335 statements.
335 statements.
336
336
337 In [1]: print 1; print 2
337 In [1]: print 1; print 2
338 1
338 1
339 2
339 2
340
340
341 In [2]: print 1,; print 2
341 In [2]: print 1,; print 2
342 1 2
342 1 2
343 """
343 """
344
344
345 def test_ofind_line_magic(self):
345 def test_ofind_line_magic(self):
346 from IPython.core.magic import register_line_magic
346 from IPython.core.magic import register_line_magic
347
347
348 @register_line_magic
348 @register_line_magic
349 def lmagic(line):
349 def lmagic(line):
350 "A line magic"
350 "A line magic"
351
351
352 # Get info on line magic
352 # Get info on line magic
353 lfind = ip._ofind('lmagic')
353 lfind = ip._ofind('lmagic')
354 info = dict(found=True, isalias=False, ismagic=True,
354 info = dict(found=True, isalias=False, ismagic=True,
355 namespace = 'IPython internal', obj= lmagic.__wrapped__,
355 namespace = 'IPython internal', obj= lmagic.__wrapped__,
356 parent = None)
356 parent = None)
357 nt.assert_equal(lfind, info)
357 nt.assert_equal(lfind, info)
358
358
359 def test_ofind_cell_magic(self):
359 def test_ofind_cell_magic(self):
360 from IPython.core.magic import register_cell_magic
360 from IPython.core.magic import register_cell_magic
361
361
362 @register_cell_magic
362 @register_cell_magic
363 def cmagic(line, cell):
363 def cmagic(line, cell):
364 "A cell magic"
364 "A cell magic"
365
365
366 # Get info on cell magic
366 # Get info on cell magic
367 find = ip._ofind('cmagic')
367 find = ip._ofind('cmagic')
368 info = dict(found=True, isalias=False, ismagic=True,
368 info = dict(found=True, isalias=False, ismagic=True,
369 namespace = 'IPython internal', obj= cmagic.__wrapped__,
369 namespace = 'IPython internal', obj= cmagic.__wrapped__,
370 parent = None)
370 parent = None)
371 nt.assert_equal(find, info)
371 nt.assert_equal(find, info)
372
372
373 def test_custom_exception(self):
373 def test_custom_exception(self):
374 called = []
374 called = []
375 def my_handler(shell, etype, value, tb, tb_offset=None):
375 def my_handler(shell, etype, value, tb, tb_offset=None):
376 called.append(etype)
376 called.append(etype)
377 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
377 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
378
378
379 ip.set_custom_exc((ValueError,), my_handler)
379 ip.set_custom_exc((ValueError,), my_handler)
380 try:
380 try:
381 ip.run_cell("raise ValueError('test')")
381 ip.run_cell("raise ValueError('test')")
382 # Check that this was called, and only once.
382 # Check that this was called, and only once.
383 self.assertEqual(called, [ValueError])
383 self.assertEqual(called, [ValueError])
384 finally:
384 finally:
385 # Reset the custom exception hook
385 # Reset the custom exception hook
386 ip.set_custom_exc((), None)
386 ip.set_custom_exc((), None)
387
387
388
388
389 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
389 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
390
390
391 def setUp(self):
391 def setUp(self):
392 self.BASETESTDIR = tempfile.mkdtemp()
392 self.BASETESTDIR = tempfile.mkdtemp()
393 self.TESTDIR = join(self.BASETESTDIR, u"Γ₯Àâ")
393 self.TESTDIR = join(self.BASETESTDIR, u"Γ₯Àâ")
394 os.mkdir(self.TESTDIR)
394 os.mkdir(self.TESTDIR)
395 with open(join(self.TESTDIR, u"Γ₯Àâtestscript.py"), "w") as sfile:
395 with open(join(self.TESTDIR, u"Γ₯Àâtestscript.py"), "w") as sfile:
396 sfile.write("pass\n")
396 sfile.write("pass\n")
397 self.oldpath = os.getcwdu()
397 self.oldpath = os.getcwdu()
398 os.chdir(self.TESTDIR)
398 os.chdir(self.TESTDIR)
399 self.fname = u"Γ₯Àâtestscript.py"
399 self.fname = u"Γ₯Àâtestscript.py"
400
400
401 def tearDown(self):
401 def tearDown(self):
402 os.chdir(self.oldpath)
402 os.chdir(self.oldpath)
403 shutil.rmtree(self.BASETESTDIR)
403 shutil.rmtree(self.BASETESTDIR)
404
404
405 def test_1(self):
405 def test_1(self):
406 """Test safe_execfile with non-ascii path
406 """Test safe_execfile with non-ascii path
407 """
407 """
408 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
408 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
409
409
410
410
411 class TestSystemRaw(unittest.TestCase):
411 class TestSystemRaw(unittest.TestCase):
412 def test_1(self):
412 def test_1(self):
413 """Test system_raw with non-ascii cmd
413 """Test system_raw with non-ascii cmd
414 """
414 """
415 cmd = ur'''python -c "'Γ₯Àâ'" '''
415 cmd = ur'''python -c "'Γ₯Àâ'" '''
416 ip.system_raw(cmd)
416 ip.system_raw(cmd)
417
418 def test_exit_code(self):
419 """Test that the exit code is parsed correctly."""
420 ip.system_raw('exit 1')
421 self.assertEqual(ip.user_ns['_exit_code'], 1)
417
422
418 class TestModules(unittest.TestCase, tt.TempFileMixin):
423 class TestModules(unittest.TestCase, tt.TempFileMixin):
419 def test_extraneous_loads(self):
424 def test_extraneous_loads(self):
420 """Test we're not loading modules on startup that we shouldn't.
425 """Test we're not loading modules on startup that we shouldn't.
421 """
426 """
422 self.mktmp("import sys\n"
427 self.mktmp("import sys\n"
423 "print('numpy' in sys.modules)\n"
428 "print('numpy' in sys.modules)\n"
424 "print('IPython.parallel' in sys.modules)\n"
429 "print('IPython.parallel' in sys.modules)\n"
425 "print('IPython.zmq' in sys.modules)\n"
430 "print('IPython.zmq' in sys.modules)\n"
426 )
431 )
427 out = "False\nFalse\nFalse\n"
432 out = "False\nFalse\nFalse\n"
428 tt.ipexec_validate(self.fname, out)
433 tt.ipexec_validate(self.fname, out)
429
434
430 class Negator(ast.NodeTransformer):
435 class Negator(ast.NodeTransformer):
431 """Negates all number literals in an AST."""
436 """Negates all number literals in an AST."""
432 def visit_Num(self, node):
437 def visit_Num(self, node):
433 node.n = -node.n
438 node.n = -node.n
434 return node
439 return node
435
440
436 class TestAstTransform(unittest.TestCase):
441 class TestAstTransform(unittest.TestCase):
437 def setUp(self):
442 def setUp(self):
438 self.negator = Negator()
443 self.negator = Negator()
439 ip.ast_transformers.append(self.negator)
444 ip.ast_transformers.append(self.negator)
440
445
441 def tearDown(self):
446 def tearDown(self):
442 ip.ast_transformers.remove(self.negator)
447 ip.ast_transformers.remove(self.negator)
443
448
444 def test_run_cell(self):
449 def test_run_cell(self):
445 with tt.AssertPrints('-34'):
450 with tt.AssertPrints('-34'):
446 ip.run_cell('print (12 + 22)')
451 ip.run_cell('print (12 + 22)')
447
452
448 # A named reference to a number shouldn't be transformed.
453 # A named reference to a number shouldn't be transformed.
449 ip.user_ns['n'] = 55
454 ip.user_ns['n'] = 55
450 with tt.AssertNotPrints('-55'):
455 with tt.AssertNotPrints('-55'):
451 ip.run_cell('print (n)')
456 ip.run_cell('print (n)')
452
457
453 def test_timeit(self):
458 def test_timeit(self):
454 called = set()
459 called = set()
455 def f(x):
460 def f(x):
456 called.add(x)
461 called.add(x)
457 ip.push({'f':f})
462 ip.push({'f':f})
458
463
459 with tt.AssertPrints("best of "):
464 with tt.AssertPrints("best of "):
460 ip.run_line_magic("timeit", "-n1 f(1)")
465 ip.run_line_magic("timeit", "-n1 f(1)")
461 self.assertEqual(called, set([-1]))
466 self.assertEqual(called, set([-1]))
462 called.clear()
467 called.clear()
463
468
464 with tt.AssertPrints("best of "):
469 with tt.AssertPrints("best of "):
465 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
470 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
466 self.assertEqual(called, set([-2, -3]))
471 self.assertEqual(called, set([-2, -3]))
467
472
468 def test_time(self):
473 def test_time(self):
469 called = []
474 called = []
470 def f(x):
475 def f(x):
471 called.append(x)
476 called.append(x)
472 ip.push({'f':f})
477 ip.push({'f':f})
473
478
474 # Test with an expression
479 # Test with an expression
475 with tt.AssertPrints("CPU times"):
480 with tt.AssertPrints("CPU times"):
476 ip.run_line_magic("time", "f(5+9)")
481 ip.run_line_magic("time", "f(5+9)")
477 self.assertEqual(called, [-14])
482 self.assertEqual(called, [-14])
478 called[:] = []
483 called[:] = []
479
484
480 # Test with a statement (different code path)
485 # Test with a statement (different code path)
481 with tt.AssertPrints("CPU times"):
486 with tt.AssertPrints("CPU times"):
482 ip.run_line_magic("time", "a = f(-3 + -2)")
487 ip.run_line_magic("time", "a = f(-3 + -2)")
483 self.assertEqual(called, [5])
488 self.assertEqual(called, [5])
484
489
485 def test_macro(self):
490 def test_macro(self):
486 ip.push({'a':10})
491 ip.push({'a':10})
487 # The AST transformation makes this do a+=-1
492 # The AST transformation makes this do a+=-1
488 ip.define_macro("amacro", "a+=1\nprint(a)")
493 ip.define_macro("amacro", "a+=1\nprint(a)")
489
494
490 with tt.AssertPrints("9"):
495 with tt.AssertPrints("9"):
491 ip.run_cell("amacro")
496 ip.run_cell("amacro")
492 with tt.AssertPrints("8"):
497 with tt.AssertPrints("8"):
493 ip.run_cell("amacro")
498 ip.run_cell("amacro")
494
499
495 class IntegerWrapper(ast.NodeTransformer):
500 class IntegerWrapper(ast.NodeTransformer):
496 """Wraps all integers in a call to Integer()"""
501 """Wraps all integers in a call to Integer()"""
497 def visit_Num(self, node):
502 def visit_Num(self, node):
498 if isinstance(node.n, int):
503 if isinstance(node.n, int):
499 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
504 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
500 args=[node], keywords=[])
505 args=[node], keywords=[])
501 return node
506 return node
502
507
503 class TestAstTransform2(unittest.TestCase):
508 class TestAstTransform2(unittest.TestCase):
504 def setUp(self):
509 def setUp(self):
505 self.intwrapper = IntegerWrapper()
510 self.intwrapper = IntegerWrapper()
506 ip.ast_transformers.append(self.intwrapper)
511 ip.ast_transformers.append(self.intwrapper)
507
512
508 self.calls = []
513 self.calls = []
509 def Integer(*args):
514 def Integer(*args):
510 self.calls.append(args)
515 self.calls.append(args)
511 return args
516 return args
512 ip.push({"Integer": Integer})
517 ip.push({"Integer": Integer})
513
518
514 def tearDown(self):
519 def tearDown(self):
515 ip.ast_transformers.remove(self.intwrapper)
520 ip.ast_transformers.remove(self.intwrapper)
516 del ip.user_ns['Integer']
521 del ip.user_ns['Integer']
517
522
518 def test_run_cell(self):
523 def test_run_cell(self):
519 ip.run_cell("n = 2")
524 ip.run_cell("n = 2")
520 self.assertEqual(self.calls, [(2,)])
525 self.assertEqual(self.calls, [(2,)])
521
526
522 # This shouldn't throw an error
527 # This shouldn't throw an error
523 ip.run_cell("o = 2.0")
528 ip.run_cell("o = 2.0")
524 self.assertEqual(ip.user_ns['o'], 2.0)
529 self.assertEqual(ip.user_ns['o'], 2.0)
525
530
526 def test_timeit(self):
531 def test_timeit(self):
527 called = set()
532 called = set()
528 def f(x):
533 def f(x):
529 called.add(x)
534 called.add(x)
530 ip.push({'f':f})
535 ip.push({'f':f})
531
536
532 with tt.AssertPrints("best of "):
537 with tt.AssertPrints("best of "):
533 ip.run_line_magic("timeit", "-n1 f(1)")
538 ip.run_line_magic("timeit", "-n1 f(1)")
534 self.assertEqual(called, set([(1,)]))
539 self.assertEqual(called, set([(1,)]))
535 called.clear()
540 called.clear()
536
541
537 with tt.AssertPrints("best of "):
542 with tt.AssertPrints("best of "):
538 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
543 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
539 self.assertEqual(called, set([(2,), (3,)]))
544 self.assertEqual(called, set([(2,), (3,)]))
540
545
541 class ErrorTransformer(ast.NodeTransformer):
546 class ErrorTransformer(ast.NodeTransformer):
542 """Throws an error when it sees a number."""
547 """Throws an error when it sees a number."""
543 def visit_Num(self):
548 def visit_Num(self):
544 raise ValueError("test")
549 raise ValueError("test")
545
550
546 class TestAstTransformError(unittest.TestCase):
551 class TestAstTransformError(unittest.TestCase):
547 def test_unregistering(self):
552 def test_unregistering(self):
548 err_transformer = ErrorTransformer()
553 err_transformer = ErrorTransformer()
549 ip.ast_transformers.append(err_transformer)
554 ip.ast_transformers.append(err_transformer)
550
555
551 with tt.AssertPrints("unregister", channel='stderr'):
556 with tt.AssertPrints("unregister", channel='stderr'):
552 ip.run_cell("1 + 2")
557 ip.run_cell("1 + 2")
553
558
554 # This should have been removed.
559 # This should have been removed.
555 nt.assert_not_in(err_transformer, ip.ast_transformers)
560 nt.assert_not_in(err_transformer, ip.ast_transformers)
556
561
557 def test__IPYTHON__():
562 def test__IPYTHON__():
558 # This shouldn't raise a NameError, that's all
563 # This shouldn't raise a NameError, that's all
559 __IPYTHON__
564 __IPYTHON__
General Comments 0
You need to be logged in to leave comments. Login now