##// END OF EJS Templates
Fix test_get_exception_only() for Python 3
Jeroen Demeyer -
Show More
@@ -1,884 +1,887 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
8
9 # Copyright (c) IPython Development Team.
9 # Copyright (c) IPython Development Team.
10 # Distributed under the terms of the Modified BSD License.
10 # Distributed under the terms of the Modified BSD License.
11
11
12 import ast
12 import ast
13 import os
13 import os
14 import signal
14 import signal
15 import shutil
15 import shutil
16 import sys
16 import sys
17 import tempfile
17 import tempfile
18 import unittest
18 import unittest
19 try:
19 try:
20 from unittest import mock
20 from unittest import mock
21 except ImportError:
21 except ImportError:
22 import mock
22 import mock
23 from os.path import join
23 from os.path import join
24
24
25 import nose.tools as nt
25 import nose.tools as nt
26
26
27 from IPython.core.error import InputRejected
27 from IPython.core.error import InputRejected
28 from IPython.core.inputtransformer import InputTransformer
28 from IPython.core.inputtransformer import InputTransformer
29 from IPython.testing.decorators import (
29 from IPython.testing.decorators import (
30 skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
30 skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
31 )
31 )
32 from IPython.testing import tools as tt
32 from IPython.testing import tools as tt
33 from IPython.utils import io
33 from IPython.utils import io
34 from IPython.utils.process import find_cmd
34 from IPython.utils.process import find_cmd
35 from IPython.utils import py3compat
35 from IPython.utils import py3compat
36 from IPython.utils.py3compat import unicode_type, PY3
36 from IPython.utils.py3compat import unicode_type, PY3
37
37
38 if PY3:
38 if PY3:
39 from io import StringIO
39 from io import StringIO
40 else:
40 else:
41 from StringIO import StringIO
41 from StringIO import StringIO
42
42
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44 # Globals
44 # Globals
45 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
46 # This is used by every single test, no point repeating it ad nauseam
46 # This is used by every single test, no point repeating it ad nauseam
47 ip = get_ipython()
47 ip = get_ipython()
48
48
49 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
50 # Tests
50 # Tests
51 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
52
52
53 class InteractiveShellTestCase(unittest.TestCase):
53 class InteractiveShellTestCase(unittest.TestCase):
54 def test_naked_string_cells(self):
54 def test_naked_string_cells(self):
55 """Test that cells with only naked strings are fully executed"""
55 """Test that cells with only naked strings are fully executed"""
56 # First, single-line inputs
56 # First, single-line inputs
57 ip.run_cell('"a"\n')
57 ip.run_cell('"a"\n')
58 self.assertEqual(ip.user_ns['_'], 'a')
58 self.assertEqual(ip.user_ns['_'], 'a')
59 # And also multi-line cells
59 # And also multi-line cells
60 ip.run_cell('"""a\nb"""\n')
60 ip.run_cell('"""a\nb"""\n')
61 self.assertEqual(ip.user_ns['_'], 'a\nb')
61 self.assertEqual(ip.user_ns['_'], 'a\nb')
62
62
63 def test_run_empty_cell(self):
63 def test_run_empty_cell(self):
64 """Just make sure we don't get a horrible error with a blank
64 """Just make sure we don't get a horrible error with a blank
65 cell of input. Yes, I did overlook that."""
65 cell of input. Yes, I did overlook that."""
66 old_xc = ip.execution_count
66 old_xc = ip.execution_count
67 ip.run_cell('')
67 ip.run_cell('')
68 self.assertEqual(ip.execution_count, old_xc)
68 self.assertEqual(ip.execution_count, old_xc)
69
69
70 def test_run_cell_multiline(self):
70 def test_run_cell_multiline(self):
71 """Multi-block, multi-line cells must execute correctly.
71 """Multi-block, multi-line cells must execute correctly.
72 """
72 """
73 src = '\n'.join(["x=1",
73 src = '\n'.join(["x=1",
74 "y=2",
74 "y=2",
75 "if 1:",
75 "if 1:",
76 " x += 1",
76 " x += 1",
77 " y += 1",])
77 " y += 1",])
78 ip.run_cell(src)
78 ip.run_cell(src)
79 self.assertEqual(ip.user_ns['x'], 2)
79 self.assertEqual(ip.user_ns['x'], 2)
80 self.assertEqual(ip.user_ns['y'], 3)
80 self.assertEqual(ip.user_ns['y'], 3)
81
81
82 def test_multiline_string_cells(self):
82 def test_multiline_string_cells(self):
83 "Code sprinkled with multiline strings should execute (GH-306)"
83 "Code sprinkled with multiline strings should execute (GH-306)"
84 ip.run_cell('tmp=0')
84 ip.run_cell('tmp=0')
85 self.assertEqual(ip.user_ns['tmp'], 0)
85 self.assertEqual(ip.user_ns['tmp'], 0)
86 ip.run_cell('tmp=1;"""a\nb"""\n')
86 ip.run_cell('tmp=1;"""a\nb"""\n')
87 self.assertEqual(ip.user_ns['tmp'], 1)
87 self.assertEqual(ip.user_ns['tmp'], 1)
88
88
89 def test_dont_cache_with_semicolon(self):
89 def test_dont_cache_with_semicolon(self):
90 "Ending a line with semicolon should not cache the returned object (GH-307)"
90 "Ending a line with semicolon should not cache the returned object (GH-307)"
91 oldlen = len(ip.user_ns['Out'])
91 oldlen = len(ip.user_ns['Out'])
92 for cell in ['1;', '1;1;']:
92 for cell in ['1;', '1;1;']:
93 ip.run_cell(cell, store_history=True)
93 ip.run_cell(cell, store_history=True)
94 newlen = len(ip.user_ns['Out'])
94 newlen = len(ip.user_ns['Out'])
95 self.assertEqual(oldlen, newlen)
95 self.assertEqual(oldlen, newlen)
96 i = 0
96 i = 0
97 #also test the default caching behavior
97 #also test the default caching behavior
98 for cell in ['1', '1;1']:
98 for cell in ['1', '1;1']:
99 ip.run_cell(cell, store_history=True)
99 ip.run_cell(cell, store_history=True)
100 newlen = len(ip.user_ns['Out'])
100 newlen = len(ip.user_ns['Out'])
101 i += 1
101 i += 1
102 self.assertEqual(oldlen+i, newlen)
102 self.assertEqual(oldlen+i, newlen)
103
103
104 def test_In_variable(self):
104 def test_In_variable(self):
105 "Verify that In variable grows with user input (GH-284)"
105 "Verify that In variable grows with user input (GH-284)"
106 oldlen = len(ip.user_ns['In'])
106 oldlen = len(ip.user_ns['In'])
107 ip.run_cell('1;', store_history=True)
107 ip.run_cell('1;', store_history=True)
108 newlen = len(ip.user_ns['In'])
108 newlen = len(ip.user_ns['In'])
109 self.assertEqual(oldlen+1, newlen)
109 self.assertEqual(oldlen+1, newlen)
110 self.assertEqual(ip.user_ns['In'][-1],'1;')
110 self.assertEqual(ip.user_ns['In'][-1],'1;')
111
111
112 def test_magic_names_in_string(self):
112 def test_magic_names_in_string(self):
113 ip.run_cell('a = """\n%exit\n"""')
113 ip.run_cell('a = """\n%exit\n"""')
114 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
114 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
115
115
116 def test_trailing_newline(self):
116 def test_trailing_newline(self):
117 """test that running !(command) does not raise a SyntaxError"""
117 """test that running !(command) does not raise a SyntaxError"""
118 ip.run_cell('!(true)\n', False)
118 ip.run_cell('!(true)\n', False)
119 ip.run_cell('!(true)\n\n\n', False)
119 ip.run_cell('!(true)\n\n\n', False)
120
120
121 def test_gh_597(self):
121 def test_gh_597(self):
122 """Pretty-printing lists of objects with non-ascii reprs may cause
122 """Pretty-printing lists of objects with non-ascii reprs may cause
123 problems."""
123 problems."""
124 class Spam(object):
124 class Spam(object):
125 def __repr__(self):
125 def __repr__(self):
126 return "\xe9"*50
126 return "\xe9"*50
127 import IPython.core.formatters
127 import IPython.core.formatters
128 f = IPython.core.formatters.PlainTextFormatter()
128 f = IPython.core.formatters.PlainTextFormatter()
129 f([Spam(),Spam()])
129 f([Spam(),Spam()])
130
130
131
131
132 def test_future_flags(self):
132 def test_future_flags(self):
133 """Check that future flags are used for parsing code (gh-777)"""
133 """Check that future flags are used for parsing code (gh-777)"""
134 ip.run_cell('from __future__ import print_function')
134 ip.run_cell('from __future__ import print_function')
135 try:
135 try:
136 ip.run_cell('prfunc_return_val = print(1,2, sep=" ")')
136 ip.run_cell('prfunc_return_val = print(1,2, sep=" ")')
137 assert 'prfunc_return_val' in ip.user_ns
137 assert 'prfunc_return_val' in ip.user_ns
138 finally:
138 finally:
139 # Reset compiler flags so we don't mess up other tests.
139 # Reset compiler flags so we don't mess up other tests.
140 ip.compile.reset_compiler_flags()
140 ip.compile.reset_compiler_flags()
141
141
142 def test_future_unicode(self):
142 def test_future_unicode(self):
143 """Check that unicode_literals is imported from __future__ (gh #786)"""
143 """Check that unicode_literals is imported from __future__ (gh #786)"""
144 try:
144 try:
145 ip.run_cell(u'byte_str = "a"')
145 ip.run_cell(u'byte_str = "a"')
146 assert isinstance(ip.user_ns['byte_str'], str) # string literals are byte strings by default
146 assert isinstance(ip.user_ns['byte_str'], str) # string literals are byte strings by default
147 ip.run_cell('from __future__ import unicode_literals')
147 ip.run_cell('from __future__ import unicode_literals')
148 ip.run_cell(u'unicode_str = "a"')
148 ip.run_cell(u'unicode_str = "a"')
149 assert isinstance(ip.user_ns['unicode_str'], unicode_type) # strings literals are now unicode
149 assert isinstance(ip.user_ns['unicode_str'], unicode_type) # strings literals are now unicode
150 finally:
150 finally:
151 # Reset compiler flags so we don't mess up other tests.
151 # Reset compiler flags so we don't mess up other tests.
152 ip.compile.reset_compiler_flags()
152 ip.compile.reset_compiler_flags()
153
153
154 def test_can_pickle(self):
154 def test_can_pickle(self):
155 "Can we pickle objects defined interactively (GH-29)"
155 "Can we pickle objects defined interactively (GH-29)"
156 ip = get_ipython()
156 ip = get_ipython()
157 ip.reset()
157 ip.reset()
158 ip.run_cell(("class Mylist(list):\n"
158 ip.run_cell(("class Mylist(list):\n"
159 " def __init__(self,x=[]):\n"
159 " def __init__(self,x=[]):\n"
160 " list.__init__(self,x)"))
160 " list.__init__(self,x)"))
161 ip.run_cell("w=Mylist([1,2,3])")
161 ip.run_cell("w=Mylist([1,2,3])")
162
162
163 from pickle import dumps
163 from pickle import dumps
164
164
165 # We need to swap in our main module - this is only necessary
165 # We need to swap in our main module - this is only necessary
166 # inside the test framework, because IPython puts the interactive module
166 # inside the test framework, because IPython puts the interactive module
167 # in place (but the test framework undoes this).
167 # in place (but the test framework undoes this).
168 _main = sys.modules['__main__']
168 _main = sys.modules['__main__']
169 sys.modules['__main__'] = ip.user_module
169 sys.modules['__main__'] = ip.user_module
170 try:
170 try:
171 res = dumps(ip.user_ns["w"])
171 res = dumps(ip.user_ns["w"])
172 finally:
172 finally:
173 sys.modules['__main__'] = _main
173 sys.modules['__main__'] = _main
174 self.assertTrue(isinstance(res, bytes))
174 self.assertTrue(isinstance(res, bytes))
175
175
176 def test_global_ns(self):
176 def test_global_ns(self):
177 "Code in functions must be able to access variables outside them."
177 "Code in functions must be able to access variables outside them."
178 ip = get_ipython()
178 ip = get_ipython()
179 ip.run_cell("a = 10")
179 ip.run_cell("a = 10")
180 ip.run_cell(("def f(x):\n"
180 ip.run_cell(("def f(x):\n"
181 " return x + a"))
181 " return x + a"))
182 ip.run_cell("b = f(12)")
182 ip.run_cell("b = f(12)")
183 self.assertEqual(ip.user_ns["b"], 22)
183 self.assertEqual(ip.user_ns["b"], 22)
184
184
185 def test_bad_custom_tb(self):
185 def test_bad_custom_tb(self):
186 """Check that InteractiveShell is protected from bad custom exception handlers"""
186 """Check that InteractiveShell is protected from bad custom exception handlers"""
187 from IPython.utils import io
187 from IPython.utils import io
188 save_stderr = io.stderr
188 save_stderr = io.stderr
189 try:
189 try:
190 # capture stderr
190 # capture stderr
191 io.stderr = StringIO()
191 io.stderr = StringIO()
192 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
192 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
193 self.assertEqual(ip.custom_exceptions, (IOError,))
193 self.assertEqual(ip.custom_exceptions, (IOError,))
194 ip.run_cell(u'raise IOError("foo")')
194 ip.run_cell(u'raise IOError("foo")')
195 self.assertEqual(ip.custom_exceptions, ())
195 self.assertEqual(ip.custom_exceptions, ())
196 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
196 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
197 finally:
197 finally:
198 io.stderr = save_stderr
198 io.stderr = save_stderr
199
199
200 def test_bad_custom_tb_return(self):
200 def test_bad_custom_tb_return(self):
201 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
201 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
202 from IPython.utils import io
202 from IPython.utils import io
203 save_stderr = io.stderr
203 save_stderr = io.stderr
204 try:
204 try:
205 # capture stderr
205 # capture stderr
206 io.stderr = StringIO()
206 io.stderr = StringIO()
207 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
207 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
208 self.assertEqual(ip.custom_exceptions, (NameError,))
208 self.assertEqual(ip.custom_exceptions, (NameError,))
209 ip.run_cell(u'a=abracadabra')
209 ip.run_cell(u'a=abracadabra')
210 self.assertEqual(ip.custom_exceptions, ())
210 self.assertEqual(ip.custom_exceptions, ())
211 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
211 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
212 finally:
212 finally:
213 io.stderr = save_stderr
213 io.stderr = save_stderr
214
214
215 def test_drop_by_id(self):
215 def test_drop_by_id(self):
216 myvars = {"a":object(), "b":object(), "c": object()}
216 myvars = {"a":object(), "b":object(), "c": object()}
217 ip.push(myvars, interactive=False)
217 ip.push(myvars, interactive=False)
218 for name in myvars:
218 for name in myvars:
219 assert name in ip.user_ns, name
219 assert name in ip.user_ns, name
220 assert name in ip.user_ns_hidden, name
220 assert name in ip.user_ns_hidden, name
221 ip.user_ns['b'] = 12
221 ip.user_ns['b'] = 12
222 ip.drop_by_id(myvars)
222 ip.drop_by_id(myvars)
223 for name in ["a", "c"]:
223 for name in ["a", "c"]:
224 assert name not in ip.user_ns, name
224 assert name not in ip.user_ns, name
225 assert name not in ip.user_ns_hidden, name
225 assert name not in ip.user_ns_hidden, name
226 assert ip.user_ns['b'] == 12
226 assert ip.user_ns['b'] == 12
227 ip.reset()
227 ip.reset()
228
228
229 def test_var_expand(self):
229 def test_var_expand(self):
230 ip.user_ns['f'] = u'Ca\xf1o'
230 ip.user_ns['f'] = u'Ca\xf1o'
231 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
231 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
232 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
232 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
233 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
233 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
234 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
234 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
235
235
236 ip.user_ns['f'] = b'Ca\xc3\xb1o'
236 ip.user_ns['f'] = b'Ca\xc3\xb1o'
237 # This should not raise any exception:
237 # This should not raise any exception:
238 ip.var_expand(u'echo $f')
238 ip.var_expand(u'echo $f')
239
239
240 def test_var_expand_local(self):
240 def test_var_expand_local(self):
241 """Test local variable expansion in !system and %magic calls"""
241 """Test local variable expansion in !system and %magic calls"""
242 # !system
242 # !system
243 ip.run_cell('def test():\n'
243 ip.run_cell('def test():\n'
244 ' lvar = "ttt"\n'
244 ' lvar = "ttt"\n'
245 ' ret = !echo {lvar}\n'
245 ' ret = !echo {lvar}\n'
246 ' return ret[0]\n')
246 ' return ret[0]\n')
247 res = ip.user_ns['test']()
247 res = ip.user_ns['test']()
248 nt.assert_in('ttt', res)
248 nt.assert_in('ttt', res)
249
249
250 # %magic
250 # %magic
251 ip.run_cell('def makemacro():\n'
251 ip.run_cell('def makemacro():\n'
252 ' macroname = "macro_var_expand_locals"\n'
252 ' macroname = "macro_var_expand_locals"\n'
253 ' %macro {macroname} codestr\n')
253 ' %macro {macroname} codestr\n')
254 ip.user_ns['codestr'] = "str(12)"
254 ip.user_ns['codestr'] = "str(12)"
255 ip.run_cell('makemacro()')
255 ip.run_cell('makemacro()')
256 nt.assert_in('macro_var_expand_locals', ip.user_ns)
256 nt.assert_in('macro_var_expand_locals', ip.user_ns)
257
257
258 def test_var_expand_self(self):
258 def test_var_expand_self(self):
259 """Test variable expansion with the name 'self', which was failing.
259 """Test variable expansion with the name 'self', which was failing.
260
260
261 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
261 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
262 """
262 """
263 ip.run_cell('class cTest:\n'
263 ip.run_cell('class cTest:\n'
264 ' classvar="see me"\n'
264 ' classvar="see me"\n'
265 ' def test(self):\n'
265 ' def test(self):\n'
266 ' res = !echo Variable: {self.classvar}\n'
266 ' res = !echo Variable: {self.classvar}\n'
267 ' return res[0]\n')
267 ' return res[0]\n')
268 nt.assert_in('see me', ip.user_ns['cTest']().test())
268 nt.assert_in('see me', ip.user_ns['cTest']().test())
269
269
270 def test_bad_var_expand(self):
270 def test_bad_var_expand(self):
271 """var_expand on invalid formats shouldn't raise"""
271 """var_expand on invalid formats shouldn't raise"""
272 # SyntaxError
272 # SyntaxError
273 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
273 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
274 # NameError
274 # NameError
275 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
275 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
276 # ZeroDivisionError
276 # ZeroDivisionError
277 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
277 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
278
278
279 def test_silent_postexec(self):
279 def test_silent_postexec(self):
280 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
280 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
281 pre_explicit = mock.Mock()
281 pre_explicit = mock.Mock()
282 pre_always = mock.Mock()
282 pre_always = mock.Mock()
283 post_explicit = mock.Mock()
283 post_explicit = mock.Mock()
284 post_always = mock.Mock()
284 post_always = mock.Mock()
285
285
286 ip.events.register('pre_run_cell', pre_explicit)
286 ip.events.register('pre_run_cell', pre_explicit)
287 ip.events.register('pre_execute', pre_always)
287 ip.events.register('pre_execute', pre_always)
288 ip.events.register('post_run_cell', post_explicit)
288 ip.events.register('post_run_cell', post_explicit)
289 ip.events.register('post_execute', post_always)
289 ip.events.register('post_execute', post_always)
290
290
291 try:
291 try:
292 ip.run_cell("1", silent=True)
292 ip.run_cell("1", silent=True)
293 assert pre_always.called
293 assert pre_always.called
294 assert not pre_explicit.called
294 assert not pre_explicit.called
295 assert post_always.called
295 assert post_always.called
296 assert not post_explicit.called
296 assert not post_explicit.called
297 # double-check that non-silent exec did what we expected
297 # double-check that non-silent exec did what we expected
298 # silent to avoid
298 # silent to avoid
299 ip.run_cell("1")
299 ip.run_cell("1")
300 assert pre_explicit.called
300 assert pre_explicit.called
301 assert post_explicit.called
301 assert post_explicit.called
302 finally:
302 finally:
303 # remove post-exec
303 # remove post-exec
304 ip.events.unregister('pre_run_cell', pre_explicit)
304 ip.events.unregister('pre_run_cell', pre_explicit)
305 ip.events.unregister('pre_execute', pre_always)
305 ip.events.unregister('pre_execute', pre_always)
306 ip.events.unregister('post_run_cell', post_explicit)
306 ip.events.unregister('post_run_cell', post_explicit)
307 ip.events.unregister('post_execute', post_always)
307 ip.events.unregister('post_execute', post_always)
308
308
309 def test_silent_noadvance(self):
309 def test_silent_noadvance(self):
310 """run_cell(silent=True) doesn't advance execution_count"""
310 """run_cell(silent=True) doesn't advance execution_count"""
311 ec = ip.execution_count
311 ec = ip.execution_count
312 # silent should force store_history=False
312 # silent should force store_history=False
313 ip.run_cell("1", store_history=True, silent=True)
313 ip.run_cell("1", store_history=True, silent=True)
314
314
315 self.assertEqual(ec, ip.execution_count)
315 self.assertEqual(ec, ip.execution_count)
316 # double-check that non-silent exec did what we expected
316 # double-check that non-silent exec did what we expected
317 # silent to avoid
317 # silent to avoid
318 ip.run_cell("1", store_history=True)
318 ip.run_cell("1", store_history=True)
319 self.assertEqual(ec+1, ip.execution_count)
319 self.assertEqual(ec+1, ip.execution_count)
320
320
321 def test_silent_nodisplayhook(self):
321 def test_silent_nodisplayhook(self):
322 """run_cell(silent=True) doesn't trigger displayhook"""
322 """run_cell(silent=True) doesn't trigger displayhook"""
323 d = dict(called=False)
323 d = dict(called=False)
324
324
325 trap = ip.display_trap
325 trap = ip.display_trap
326 save_hook = trap.hook
326 save_hook = trap.hook
327
327
328 def failing_hook(*args, **kwargs):
328 def failing_hook(*args, **kwargs):
329 d['called'] = True
329 d['called'] = True
330
330
331 try:
331 try:
332 trap.hook = failing_hook
332 trap.hook = failing_hook
333 ip.run_cell("1", silent=True)
333 ip.run_cell("1", silent=True)
334 self.assertFalse(d['called'])
334 self.assertFalse(d['called'])
335 # double-check that non-silent exec did what we expected
335 # double-check that non-silent exec did what we expected
336 # silent to avoid
336 # silent to avoid
337 ip.run_cell("1")
337 ip.run_cell("1")
338 self.assertTrue(d['called'])
338 self.assertTrue(d['called'])
339 finally:
339 finally:
340 trap.hook = save_hook
340 trap.hook = save_hook
341
341
342 @skipif(sys.version_info[0] >= 3, "softspace removed in py3")
342 @skipif(sys.version_info[0] >= 3, "softspace removed in py3")
343 def test_print_softspace(self):
343 def test_print_softspace(self):
344 """Verify that softspace is handled correctly when executing multiple
344 """Verify that softspace is handled correctly when executing multiple
345 statements.
345 statements.
346
346
347 In [1]: print 1; print 2
347 In [1]: print 1; print 2
348 1
348 1
349 2
349 2
350
350
351 In [2]: print 1,; print 2
351 In [2]: print 1,; print 2
352 1 2
352 1 2
353 """
353 """
354
354
355 def test_ofind_line_magic(self):
355 def test_ofind_line_magic(self):
356 from IPython.core.magic import register_line_magic
356 from IPython.core.magic import register_line_magic
357
357
358 @register_line_magic
358 @register_line_magic
359 def lmagic(line):
359 def lmagic(line):
360 "A line magic"
360 "A line magic"
361
361
362 # Get info on line magic
362 # Get info on line magic
363 lfind = ip._ofind('lmagic')
363 lfind = ip._ofind('lmagic')
364 info = dict(found=True, isalias=False, ismagic=True,
364 info = dict(found=True, isalias=False, ismagic=True,
365 namespace = 'IPython internal', obj= lmagic.__wrapped__,
365 namespace = 'IPython internal', obj= lmagic.__wrapped__,
366 parent = None)
366 parent = None)
367 nt.assert_equal(lfind, info)
367 nt.assert_equal(lfind, info)
368
368
369 def test_ofind_cell_magic(self):
369 def test_ofind_cell_magic(self):
370 from IPython.core.magic import register_cell_magic
370 from IPython.core.magic import register_cell_magic
371
371
372 @register_cell_magic
372 @register_cell_magic
373 def cmagic(line, cell):
373 def cmagic(line, cell):
374 "A cell magic"
374 "A cell magic"
375
375
376 # Get info on cell magic
376 # Get info on cell magic
377 find = ip._ofind('cmagic')
377 find = ip._ofind('cmagic')
378 info = dict(found=True, isalias=False, ismagic=True,
378 info = dict(found=True, isalias=False, ismagic=True,
379 namespace = 'IPython internal', obj= cmagic.__wrapped__,
379 namespace = 'IPython internal', obj= cmagic.__wrapped__,
380 parent = None)
380 parent = None)
381 nt.assert_equal(find, info)
381 nt.assert_equal(find, info)
382
382
383 def test_ofind_property_with_error(self):
383 def test_ofind_property_with_error(self):
384 class A(object):
384 class A(object):
385 @property
385 @property
386 def foo(self):
386 def foo(self):
387 raise NotImplementedError()
387 raise NotImplementedError()
388 a = A()
388 a = A()
389
389
390 found = ip._ofind('a.foo', [('locals', locals())])
390 found = ip._ofind('a.foo', [('locals', locals())])
391 info = dict(found=True, isalias=False, ismagic=False,
391 info = dict(found=True, isalias=False, ismagic=False,
392 namespace='locals', obj=A.foo, parent=a)
392 namespace='locals', obj=A.foo, parent=a)
393 nt.assert_equal(found, info)
393 nt.assert_equal(found, info)
394
394
395 def test_ofind_multiple_attribute_lookups(self):
395 def test_ofind_multiple_attribute_lookups(self):
396 class A(object):
396 class A(object):
397 @property
397 @property
398 def foo(self):
398 def foo(self):
399 raise NotImplementedError()
399 raise NotImplementedError()
400
400
401 a = A()
401 a = A()
402 a.a = A()
402 a.a = A()
403 a.a.a = A()
403 a.a.a = A()
404
404
405 found = ip._ofind('a.a.a.foo', [('locals', locals())])
405 found = ip._ofind('a.a.a.foo', [('locals', locals())])
406 info = dict(found=True, isalias=False, ismagic=False,
406 info = dict(found=True, isalias=False, ismagic=False,
407 namespace='locals', obj=A.foo, parent=a.a.a)
407 namespace='locals', obj=A.foo, parent=a.a.a)
408 nt.assert_equal(found, info)
408 nt.assert_equal(found, info)
409
409
410 def test_ofind_slotted_attributes(self):
410 def test_ofind_slotted_attributes(self):
411 class A(object):
411 class A(object):
412 __slots__ = ['foo']
412 __slots__ = ['foo']
413 def __init__(self):
413 def __init__(self):
414 self.foo = 'bar'
414 self.foo = 'bar'
415
415
416 a = A()
416 a = A()
417 found = ip._ofind('a.foo', [('locals', locals())])
417 found = ip._ofind('a.foo', [('locals', locals())])
418 info = dict(found=True, isalias=False, ismagic=False,
418 info = dict(found=True, isalias=False, ismagic=False,
419 namespace='locals', obj=a.foo, parent=a)
419 namespace='locals', obj=a.foo, parent=a)
420 nt.assert_equal(found, info)
420 nt.assert_equal(found, info)
421
421
422 found = ip._ofind('a.bar', [('locals', locals())])
422 found = ip._ofind('a.bar', [('locals', locals())])
423 info = dict(found=False, isalias=False, ismagic=False,
423 info = dict(found=False, isalias=False, ismagic=False,
424 namespace=None, obj=None, parent=a)
424 namespace=None, obj=None, parent=a)
425 nt.assert_equal(found, info)
425 nt.assert_equal(found, info)
426
426
427 def test_ofind_prefers_property_to_instance_level_attribute(self):
427 def test_ofind_prefers_property_to_instance_level_attribute(self):
428 class A(object):
428 class A(object):
429 @property
429 @property
430 def foo(self):
430 def foo(self):
431 return 'bar'
431 return 'bar'
432 a = A()
432 a = A()
433 a.__dict__['foo'] = 'baz'
433 a.__dict__['foo'] = 'baz'
434 nt.assert_equal(a.foo, 'bar')
434 nt.assert_equal(a.foo, 'bar')
435 found = ip._ofind('a.foo', [('locals', locals())])
435 found = ip._ofind('a.foo', [('locals', locals())])
436 nt.assert_is(found['obj'], A.foo)
436 nt.assert_is(found['obj'], A.foo)
437
437
438 def test_custom_exception(self):
438 def test_custom_exception(self):
439 called = []
439 called = []
440 def my_handler(shell, etype, value, tb, tb_offset=None):
440 def my_handler(shell, etype, value, tb, tb_offset=None):
441 called.append(etype)
441 called.append(etype)
442 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
442 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
443
443
444 ip.set_custom_exc((ValueError,), my_handler)
444 ip.set_custom_exc((ValueError,), my_handler)
445 try:
445 try:
446 ip.run_cell("raise ValueError('test')")
446 ip.run_cell("raise ValueError('test')")
447 # Check that this was called, and only once.
447 # Check that this was called, and only once.
448 self.assertEqual(called, [ValueError])
448 self.assertEqual(called, [ValueError])
449 finally:
449 finally:
450 # Reset the custom exception hook
450 # Reset the custom exception hook
451 ip.set_custom_exc((), None)
451 ip.set_custom_exc((), None)
452
452
453 @skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
453 @skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
454 def test_future_environment(self):
454 def test_future_environment(self):
455 "Can we run code with & without the shell's __future__ imports?"
455 "Can we run code with & without the shell's __future__ imports?"
456 ip.run_cell("from __future__ import division")
456 ip.run_cell("from __future__ import division")
457 ip.run_cell("a = 1/2", shell_futures=True)
457 ip.run_cell("a = 1/2", shell_futures=True)
458 self.assertEqual(ip.user_ns['a'], 0.5)
458 self.assertEqual(ip.user_ns['a'], 0.5)
459 ip.run_cell("b = 1/2", shell_futures=False)
459 ip.run_cell("b = 1/2", shell_futures=False)
460 self.assertEqual(ip.user_ns['b'], 0)
460 self.assertEqual(ip.user_ns['b'], 0)
461
461
462 ip.compile.reset_compiler_flags()
462 ip.compile.reset_compiler_flags()
463 # This shouldn't leak to the shell's compiler
463 # This shouldn't leak to the shell's compiler
464 ip.run_cell("from __future__ import division \nc=1/2", shell_futures=False)
464 ip.run_cell("from __future__ import division \nc=1/2", shell_futures=False)
465 self.assertEqual(ip.user_ns['c'], 0.5)
465 self.assertEqual(ip.user_ns['c'], 0.5)
466 ip.run_cell("d = 1/2", shell_futures=True)
466 ip.run_cell("d = 1/2", shell_futures=True)
467 self.assertEqual(ip.user_ns['d'], 0)
467 self.assertEqual(ip.user_ns['d'], 0)
468
468
469 def test_mktempfile(self):
469 def test_mktempfile(self):
470 filename = ip.mktempfile()
470 filename = ip.mktempfile()
471 # Check that we can open the file again on Windows
471 # Check that we can open the file again on Windows
472 with open(filename, 'w') as f:
472 with open(filename, 'w') as f:
473 f.write('abc')
473 f.write('abc')
474
474
475 filename = ip.mktempfile(data='blah')
475 filename = ip.mktempfile(data='blah')
476 with open(filename, 'r') as f:
476 with open(filename, 'r') as f:
477 self.assertEqual(f.read(), 'blah')
477 self.assertEqual(f.read(), 'blah')
478
478
479 def test_new_main_mod(self):
479 def test_new_main_mod(self):
480 # Smoketest to check that this accepts a unicode module name
480 # Smoketest to check that this accepts a unicode module name
481 name = u'jiefmw'
481 name = u'jiefmw'
482 mod = ip.new_main_mod(u'%s.py' % name, name)
482 mod = ip.new_main_mod(u'%s.py' % name, name)
483 self.assertEqual(mod.__name__, name)
483 self.assertEqual(mod.__name__, name)
484
484
485 def test_get_exception_only(self):
485 def test_get_exception_only(self):
486 try:
486 try:
487 raise KeyboardInterrupt
487 raise KeyboardInterrupt
488 except KeyboardInterrupt:
488 except KeyboardInterrupt:
489 msg = ip.get_exception_only()
489 msg = ip.get_exception_only()
490 self.assertEqual(msg, 'KeyboardInterrupt\n')
490 self.assertEqual(msg, 'KeyboardInterrupt\n')
491
491
492 class DerivedInterrupt(KeyboardInterrupt):
492 class DerivedInterrupt(KeyboardInterrupt):
493 pass
493 pass
494 try:
494 try:
495 raise DerivedInterrupt("foo")
495 raise DerivedInterrupt("foo")
496 except KeyboardInterrupt:
496 except KeyboardInterrupt:
497 msg = ip.get_exception_only()
497 msg = ip.get_exception_only()
498 self.assertEqual(msg, 'DerivedInterrupt: foo\n')
498 if sys.version_info[0] <= 2:
499 self.assertEqual(msg, 'DerivedInterrupt: foo\n')
500 else:
501 self.assertEqual(msg, 'IPython.core.tests.test_interactiveshell.DerivedInterrupt: foo\n')
499
502
500 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
503 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
501
504
502 @onlyif_unicode_paths
505 @onlyif_unicode_paths
503 def setUp(self):
506 def setUp(self):
504 self.BASETESTDIR = tempfile.mkdtemp()
507 self.BASETESTDIR = tempfile.mkdtemp()
505 self.TESTDIR = join(self.BASETESTDIR, u"Γ₯Àâ")
508 self.TESTDIR = join(self.BASETESTDIR, u"Γ₯Àâ")
506 os.mkdir(self.TESTDIR)
509 os.mkdir(self.TESTDIR)
507 with open(join(self.TESTDIR, u"Γ₯Àâtestscript.py"), "w") as sfile:
510 with open(join(self.TESTDIR, u"Γ₯Àâtestscript.py"), "w") as sfile:
508 sfile.write("pass\n")
511 sfile.write("pass\n")
509 self.oldpath = py3compat.getcwd()
512 self.oldpath = py3compat.getcwd()
510 os.chdir(self.TESTDIR)
513 os.chdir(self.TESTDIR)
511 self.fname = u"Γ₯Àâtestscript.py"
514 self.fname = u"Γ₯Àâtestscript.py"
512
515
513 def tearDown(self):
516 def tearDown(self):
514 os.chdir(self.oldpath)
517 os.chdir(self.oldpath)
515 shutil.rmtree(self.BASETESTDIR)
518 shutil.rmtree(self.BASETESTDIR)
516
519
517 @onlyif_unicode_paths
520 @onlyif_unicode_paths
518 def test_1(self):
521 def test_1(self):
519 """Test safe_execfile with non-ascii path
522 """Test safe_execfile with non-ascii path
520 """
523 """
521 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
524 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
522
525
523 class ExitCodeChecks(tt.TempFileMixin):
526 class ExitCodeChecks(tt.TempFileMixin):
524 def test_exit_code_ok(self):
527 def test_exit_code_ok(self):
525 self.system('exit 0')
528 self.system('exit 0')
526 self.assertEqual(ip.user_ns['_exit_code'], 0)
529 self.assertEqual(ip.user_ns['_exit_code'], 0)
527
530
528 def test_exit_code_error(self):
531 def test_exit_code_error(self):
529 self.system('exit 1')
532 self.system('exit 1')
530 self.assertEqual(ip.user_ns['_exit_code'], 1)
533 self.assertEqual(ip.user_ns['_exit_code'], 1)
531
534
532 @skipif(not hasattr(signal, 'SIGALRM'))
535 @skipif(not hasattr(signal, 'SIGALRM'))
533 def test_exit_code_signal(self):
536 def test_exit_code_signal(self):
534 self.mktmp("import signal, time\n"
537 self.mktmp("import signal, time\n"
535 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
538 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
536 "time.sleep(1)\n")
539 "time.sleep(1)\n")
537 self.system("%s %s" % (sys.executable, self.fname))
540 self.system("%s %s" % (sys.executable, self.fname))
538 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
541 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
539
542
540 @onlyif_cmds_exist("csh")
543 @onlyif_cmds_exist("csh")
541 def test_exit_code_signal_csh(self):
544 def test_exit_code_signal_csh(self):
542 SHELL = os.environ.get('SHELL', None)
545 SHELL = os.environ.get('SHELL', None)
543 os.environ['SHELL'] = find_cmd("csh")
546 os.environ['SHELL'] = find_cmd("csh")
544 try:
547 try:
545 self.test_exit_code_signal()
548 self.test_exit_code_signal()
546 finally:
549 finally:
547 if SHELL is not None:
550 if SHELL is not None:
548 os.environ['SHELL'] = SHELL
551 os.environ['SHELL'] = SHELL
549 else:
552 else:
550 del os.environ['SHELL']
553 del os.environ['SHELL']
551
554
552 class TestSystemRaw(unittest.TestCase, ExitCodeChecks):
555 class TestSystemRaw(unittest.TestCase, ExitCodeChecks):
553 system = ip.system_raw
556 system = ip.system_raw
554
557
555 @onlyif_unicode_paths
558 @onlyif_unicode_paths
556 def test_1(self):
559 def test_1(self):
557 """Test system_raw with non-ascii cmd
560 """Test system_raw with non-ascii cmd
558 """
561 """
559 cmd = u'''python -c "'Γ₯Àâ'" '''
562 cmd = u'''python -c "'Γ₯Àâ'" '''
560 ip.system_raw(cmd)
563 ip.system_raw(cmd)
561
564
562 @mock.patch('subprocess.call', side_effect=KeyboardInterrupt)
565 @mock.patch('subprocess.call', side_effect=KeyboardInterrupt)
563 @mock.patch('os.system', side_effect=KeyboardInterrupt)
566 @mock.patch('os.system', side_effect=KeyboardInterrupt)
564 def test_control_c(self, *mocks):
567 def test_control_c(self, *mocks):
565 try:
568 try:
566 self.system("sleep 1 # wont happen")
569 self.system("sleep 1 # wont happen")
567 except KeyboardInterrupt:
570 except KeyboardInterrupt:
568 self.fail("system call should intercept "
571 self.fail("system call should intercept "
569 "keyboard interrupt from subprocess.call")
572 "keyboard interrupt from subprocess.call")
570 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGINT)
573 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGINT)
571
574
572 # TODO: Exit codes are currently ignored on Windows.
575 # TODO: Exit codes are currently ignored on Windows.
573 class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks):
576 class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks):
574 system = ip.system_piped
577 system = ip.system_piped
575
578
576 @skip_win32
579 @skip_win32
577 def test_exit_code_ok(self):
580 def test_exit_code_ok(self):
578 ExitCodeChecks.test_exit_code_ok(self)
581 ExitCodeChecks.test_exit_code_ok(self)
579
582
580 @skip_win32
583 @skip_win32
581 def test_exit_code_error(self):
584 def test_exit_code_error(self):
582 ExitCodeChecks.test_exit_code_error(self)
585 ExitCodeChecks.test_exit_code_error(self)
583
586
584 @skip_win32
587 @skip_win32
585 def test_exit_code_signal(self):
588 def test_exit_code_signal(self):
586 ExitCodeChecks.test_exit_code_signal(self)
589 ExitCodeChecks.test_exit_code_signal(self)
587
590
588 class TestModules(unittest.TestCase, tt.TempFileMixin):
591 class TestModules(unittest.TestCase, tt.TempFileMixin):
589 def test_extraneous_loads(self):
592 def test_extraneous_loads(self):
590 """Test we're not loading modules on startup that we shouldn't.
593 """Test we're not loading modules on startup that we shouldn't.
591 """
594 """
592 self.mktmp("import sys\n"
595 self.mktmp("import sys\n"
593 "print('numpy' in sys.modules)\n"
596 "print('numpy' in sys.modules)\n"
594 "print('IPython.parallel' in sys.modules)\n"
597 "print('IPython.parallel' in sys.modules)\n"
595 "print('IPython.kernel.zmq' in sys.modules)\n"
598 "print('IPython.kernel.zmq' in sys.modules)\n"
596 )
599 )
597 out = "False\nFalse\nFalse\n"
600 out = "False\nFalse\nFalse\n"
598 tt.ipexec_validate(self.fname, out)
601 tt.ipexec_validate(self.fname, out)
599
602
600 class Negator(ast.NodeTransformer):
603 class Negator(ast.NodeTransformer):
601 """Negates all number literals in an AST."""
604 """Negates all number literals in an AST."""
602 def visit_Num(self, node):
605 def visit_Num(self, node):
603 node.n = -node.n
606 node.n = -node.n
604 return node
607 return node
605
608
606 class TestAstTransform(unittest.TestCase):
609 class TestAstTransform(unittest.TestCase):
607 def setUp(self):
610 def setUp(self):
608 self.negator = Negator()
611 self.negator = Negator()
609 ip.ast_transformers.append(self.negator)
612 ip.ast_transformers.append(self.negator)
610
613
611 def tearDown(self):
614 def tearDown(self):
612 ip.ast_transformers.remove(self.negator)
615 ip.ast_transformers.remove(self.negator)
613
616
614 def test_run_cell(self):
617 def test_run_cell(self):
615 with tt.AssertPrints('-34'):
618 with tt.AssertPrints('-34'):
616 ip.run_cell('print (12 + 22)')
619 ip.run_cell('print (12 + 22)')
617
620
618 # A named reference to a number shouldn't be transformed.
621 # A named reference to a number shouldn't be transformed.
619 ip.user_ns['n'] = 55
622 ip.user_ns['n'] = 55
620 with tt.AssertNotPrints('-55'):
623 with tt.AssertNotPrints('-55'):
621 ip.run_cell('print (n)')
624 ip.run_cell('print (n)')
622
625
623 def test_timeit(self):
626 def test_timeit(self):
624 called = set()
627 called = set()
625 def f(x):
628 def f(x):
626 called.add(x)
629 called.add(x)
627 ip.push({'f':f})
630 ip.push({'f':f})
628
631
629 with tt.AssertPrints("best of "):
632 with tt.AssertPrints("best of "):
630 ip.run_line_magic("timeit", "-n1 f(1)")
633 ip.run_line_magic("timeit", "-n1 f(1)")
631 self.assertEqual(called, set([-1]))
634 self.assertEqual(called, set([-1]))
632 called.clear()
635 called.clear()
633
636
634 with tt.AssertPrints("best of "):
637 with tt.AssertPrints("best of "):
635 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
638 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
636 self.assertEqual(called, set([-2, -3]))
639 self.assertEqual(called, set([-2, -3]))
637
640
638 def test_time(self):
641 def test_time(self):
639 called = []
642 called = []
640 def f(x):
643 def f(x):
641 called.append(x)
644 called.append(x)
642 ip.push({'f':f})
645 ip.push({'f':f})
643
646
644 # Test with an expression
647 # Test with an expression
645 with tt.AssertPrints("Wall time: "):
648 with tt.AssertPrints("Wall time: "):
646 ip.run_line_magic("time", "f(5+9)")
649 ip.run_line_magic("time", "f(5+9)")
647 self.assertEqual(called, [-14])
650 self.assertEqual(called, [-14])
648 called[:] = []
651 called[:] = []
649
652
650 # Test with a statement (different code path)
653 # Test with a statement (different code path)
651 with tt.AssertPrints("Wall time: "):
654 with tt.AssertPrints("Wall time: "):
652 ip.run_line_magic("time", "a = f(-3 + -2)")
655 ip.run_line_magic("time", "a = f(-3 + -2)")
653 self.assertEqual(called, [5])
656 self.assertEqual(called, [5])
654
657
655 def test_macro(self):
658 def test_macro(self):
656 ip.push({'a':10})
659 ip.push({'a':10})
657 # The AST transformation makes this do a+=-1
660 # The AST transformation makes this do a+=-1
658 ip.define_macro("amacro", "a+=1\nprint(a)")
661 ip.define_macro("amacro", "a+=1\nprint(a)")
659
662
660 with tt.AssertPrints("9"):
663 with tt.AssertPrints("9"):
661 ip.run_cell("amacro")
664 ip.run_cell("amacro")
662 with tt.AssertPrints("8"):
665 with tt.AssertPrints("8"):
663 ip.run_cell("amacro")
666 ip.run_cell("amacro")
664
667
665 class IntegerWrapper(ast.NodeTransformer):
668 class IntegerWrapper(ast.NodeTransformer):
666 """Wraps all integers in a call to Integer()"""
669 """Wraps all integers in a call to Integer()"""
667 def visit_Num(self, node):
670 def visit_Num(self, node):
668 if isinstance(node.n, int):
671 if isinstance(node.n, int):
669 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
672 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
670 args=[node], keywords=[])
673 args=[node], keywords=[])
671 return node
674 return node
672
675
673 class TestAstTransform2(unittest.TestCase):
676 class TestAstTransform2(unittest.TestCase):
674 def setUp(self):
677 def setUp(self):
675 self.intwrapper = IntegerWrapper()
678 self.intwrapper = IntegerWrapper()
676 ip.ast_transformers.append(self.intwrapper)
679 ip.ast_transformers.append(self.intwrapper)
677
680
678 self.calls = []
681 self.calls = []
679 def Integer(*args):
682 def Integer(*args):
680 self.calls.append(args)
683 self.calls.append(args)
681 return args
684 return args
682 ip.push({"Integer": Integer})
685 ip.push({"Integer": Integer})
683
686
684 def tearDown(self):
687 def tearDown(self):
685 ip.ast_transformers.remove(self.intwrapper)
688 ip.ast_transformers.remove(self.intwrapper)
686 del ip.user_ns['Integer']
689 del ip.user_ns['Integer']
687
690
688 def test_run_cell(self):
691 def test_run_cell(self):
689 ip.run_cell("n = 2")
692 ip.run_cell("n = 2")
690 self.assertEqual(self.calls, [(2,)])
693 self.assertEqual(self.calls, [(2,)])
691
694
692 # This shouldn't throw an error
695 # This shouldn't throw an error
693 ip.run_cell("o = 2.0")
696 ip.run_cell("o = 2.0")
694 self.assertEqual(ip.user_ns['o'], 2.0)
697 self.assertEqual(ip.user_ns['o'], 2.0)
695
698
696 def test_timeit(self):
699 def test_timeit(self):
697 called = set()
700 called = set()
698 def f(x):
701 def f(x):
699 called.add(x)
702 called.add(x)
700 ip.push({'f':f})
703 ip.push({'f':f})
701
704
702 with tt.AssertPrints("best of "):
705 with tt.AssertPrints("best of "):
703 ip.run_line_magic("timeit", "-n1 f(1)")
706 ip.run_line_magic("timeit", "-n1 f(1)")
704 self.assertEqual(called, set([(1,)]))
707 self.assertEqual(called, set([(1,)]))
705 called.clear()
708 called.clear()
706
709
707 with tt.AssertPrints("best of "):
710 with tt.AssertPrints("best of "):
708 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
711 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
709 self.assertEqual(called, set([(2,), (3,)]))
712 self.assertEqual(called, set([(2,), (3,)]))
710
713
711 class ErrorTransformer(ast.NodeTransformer):
714 class ErrorTransformer(ast.NodeTransformer):
712 """Throws an error when it sees a number."""
715 """Throws an error when it sees a number."""
713 def visit_Num(self, node):
716 def visit_Num(self, node):
714 raise ValueError("test")
717 raise ValueError("test")
715
718
716 class TestAstTransformError(unittest.TestCase):
719 class TestAstTransformError(unittest.TestCase):
717 def test_unregistering(self):
720 def test_unregistering(self):
718 err_transformer = ErrorTransformer()
721 err_transformer = ErrorTransformer()
719 ip.ast_transformers.append(err_transformer)
722 ip.ast_transformers.append(err_transformer)
720
723
721 with tt.AssertPrints("unregister", channel='stderr'):
724 with tt.AssertPrints("unregister", channel='stderr'):
722 ip.run_cell("1 + 2")
725 ip.run_cell("1 + 2")
723
726
724 # This should have been removed.
727 # This should have been removed.
725 nt.assert_not_in(err_transformer, ip.ast_transformers)
728 nt.assert_not_in(err_transformer, ip.ast_transformers)
726
729
727
730
728 class StringRejector(ast.NodeTransformer):
731 class StringRejector(ast.NodeTransformer):
729 """Throws an InputRejected when it sees a string literal.
732 """Throws an InputRejected when it sees a string literal.
730
733
731 Used to verify that NodeTransformers can signal that a piece of code should
734 Used to verify that NodeTransformers can signal that a piece of code should
732 not be executed by throwing an InputRejected.
735 not be executed by throwing an InputRejected.
733 """
736 """
734
737
735 def visit_Str(self, node):
738 def visit_Str(self, node):
736 raise InputRejected("test")
739 raise InputRejected("test")
737
740
738
741
739 class TestAstTransformInputRejection(unittest.TestCase):
742 class TestAstTransformInputRejection(unittest.TestCase):
740
743
741 def setUp(self):
744 def setUp(self):
742 self.transformer = StringRejector()
745 self.transformer = StringRejector()
743 ip.ast_transformers.append(self.transformer)
746 ip.ast_transformers.append(self.transformer)
744
747
745 def tearDown(self):
748 def tearDown(self):
746 ip.ast_transformers.remove(self.transformer)
749 ip.ast_transformers.remove(self.transformer)
747
750
748 def test_input_rejection(self):
751 def test_input_rejection(self):
749 """Check that NodeTransformers can reject input."""
752 """Check that NodeTransformers can reject input."""
750
753
751 expect_exception_tb = tt.AssertPrints("InputRejected: test")
754 expect_exception_tb = tt.AssertPrints("InputRejected: test")
752 expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False)
755 expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False)
753
756
754 # Run the same check twice to verify that the transformer is not
757 # Run the same check twice to verify that the transformer is not
755 # disabled after raising.
758 # disabled after raising.
756 with expect_exception_tb, expect_no_cell_output:
759 with expect_exception_tb, expect_no_cell_output:
757 ip.run_cell("'unsafe'")
760 ip.run_cell("'unsafe'")
758
761
759 with expect_exception_tb, expect_no_cell_output:
762 with expect_exception_tb, expect_no_cell_output:
760 ip.run_cell("'unsafe'")
763 ip.run_cell("'unsafe'")
761
764
762 def test__IPYTHON__():
765 def test__IPYTHON__():
763 # This shouldn't raise a NameError, that's all
766 # This shouldn't raise a NameError, that's all
764 __IPYTHON__
767 __IPYTHON__
765
768
766
769
767 class DummyRepr(object):
770 class DummyRepr(object):
768 def __repr__(self):
771 def __repr__(self):
769 return "DummyRepr"
772 return "DummyRepr"
770
773
771 def _repr_html_(self):
774 def _repr_html_(self):
772 return "<b>dummy</b>"
775 return "<b>dummy</b>"
773
776
774 def _repr_javascript_(self):
777 def _repr_javascript_(self):
775 return "console.log('hi');", {'key': 'value'}
778 return "console.log('hi');", {'key': 'value'}
776
779
777
780
778 def test_user_variables():
781 def test_user_variables():
779 # enable all formatters
782 # enable all formatters
780 ip.display_formatter.active_types = ip.display_formatter.format_types
783 ip.display_formatter.active_types = ip.display_formatter.format_types
781
784
782 ip.user_ns['dummy'] = d = DummyRepr()
785 ip.user_ns['dummy'] = d = DummyRepr()
783 keys = set(['dummy', 'doesnotexist'])
786 keys = set(['dummy', 'doesnotexist'])
784 r = ip.user_expressions({ key:key for key in keys})
787 r = ip.user_expressions({ key:key for key in keys})
785
788
786 nt.assert_equal(keys, set(r.keys()))
789 nt.assert_equal(keys, set(r.keys()))
787 dummy = r['dummy']
790 dummy = r['dummy']
788 nt.assert_equal(set(['status', 'data', 'metadata']), set(dummy.keys()))
791 nt.assert_equal(set(['status', 'data', 'metadata']), set(dummy.keys()))
789 nt.assert_equal(dummy['status'], 'ok')
792 nt.assert_equal(dummy['status'], 'ok')
790 data = dummy['data']
793 data = dummy['data']
791 metadata = dummy['metadata']
794 metadata = dummy['metadata']
792 nt.assert_equal(data.get('text/html'), d._repr_html_())
795 nt.assert_equal(data.get('text/html'), d._repr_html_())
793 js, jsmd = d._repr_javascript_()
796 js, jsmd = d._repr_javascript_()
794 nt.assert_equal(data.get('application/javascript'), js)
797 nt.assert_equal(data.get('application/javascript'), js)
795 nt.assert_equal(metadata.get('application/javascript'), jsmd)
798 nt.assert_equal(metadata.get('application/javascript'), jsmd)
796
799
797 dne = r['doesnotexist']
800 dne = r['doesnotexist']
798 nt.assert_equal(dne['status'], 'error')
801 nt.assert_equal(dne['status'], 'error')
799 nt.assert_equal(dne['ename'], 'NameError')
802 nt.assert_equal(dne['ename'], 'NameError')
800
803
801 # back to text only
804 # back to text only
802 ip.display_formatter.active_types = ['text/plain']
805 ip.display_formatter.active_types = ['text/plain']
803
806
804 def test_user_expression():
807 def test_user_expression():
805 # enable all formatters
808 # enable all formatters
806 ip.display_formatter.active_types = ip.display_formatter.format_types
809 ip.display_formatter.active_types = ip.display_formatter.format_types
807 query = {
810 query = {
808 'a' : '1 + 2',
811 'a' : '1 + 2',
809 'b' : '1/0',
812 'b' : '1/0',
810 }
813 }
811 r = ip.user_expressions(query)
814 r = ip.user_expressions(query)
812 import pprint
815 import pprint
813 pprint.pprint(r)
816 pprint.pprint(r)
814 nt.assert_equal(set(r.keys()), set(query.keys()))
817 nt.assert_equal(set(r.keys()), set(query.keys()))
815 a = r['a']
818 a = r['a']
816 nt.assert_equal(set(['status', 'data', 'metadata']), set(a.keys()))
819 nt.assert_equal(set(['status', 'data', 'metadata']), set(a.keys()))
817 nt.assert_equal(a['status'], 'ok')
820 nt.assert_equal(a['status'], 'ok')
818 data = a['data']
821 data = a['data']
819 metadata = a['metadata']
822 metadata = a['metadata']
820 nt.assert_equal(data.get('text/plain'), '3')
823 nt.assert_equal(data.get('text/plain'), '3')
821
824
822 b = r['b']
825 b = r['b']
823 nt.assert_equal(b['status'], 'error')
826 nt.assert_equal(b['status'], 'error')
824 nt.assert_equal(b['ename'], 'ZeroDivisionError')
827 nt.assert_equal(b['ename'], 'ZeroDivisionError')
825
828
826 # back to text only
829 # back to text only
827 ip.display_formatter.active_types = ['text/plain']
830 ip.display_formatter.active_types = ['text/plain']
828
831
829
832
830
833
831
834
832
835
833 class TestSyntaxErrorTransformer(unittest.TestCase):
836 class TestSyntaxErrorTransformer(unittest.TestCase):
834 """Check that SyntaxError raised by an input transformer is handled by run_cell()"""
837 """Check that SyntaxError raised by an input transformer is handled by run_cell()"""
835
838
836 class SyntaxErrorTransformer(InputTransformer):
839 class SyntaxErrorTransformer(InputTransformer):
837
840
838 def push(self, line):
841 def push(self, line):
839 pos = line.find('syntaxerror')
842 pos = line.find('syntaxerror')
840 if pos >= 0:
843 if pos >= 0:
841 e = SyntaxError('input contains "syntaxerror"')
844 e = SyntaxError('input contains "syntaxerror"')
842 e.text = line
845 e.text = line
843 e.offset = pos + 1
846 e.offset = pos + 1
844 raise e
847 raise e
845 return line
848 return line
846
849
847 def reset(self):
850 def reset(self):
848 pass
851 pass
849
852
850 def setUp(self):
853 def setUp(self):
851 self.transformer = TestSyntaxErrorTransformer.SyntaxErrorTransformer()
854 self.transformer = TestSyntaxErrorTransformer.SyntaxErrorTransformer()
852 ip.input_splitter.python_line_transforms.append(self.transformer)
855 ip.input_splitter.python_line_transforms.append(self.transformer)
853 ip.input_transformer_manager.python_line_transforms.append(self.transformer)
856 ip.input_transformer_manager.python_line_transforms.append(self.transformer)
854
857
855 def tearDown(self):
858 def tearDown(self):
856 ip.input_splitter.python_line_transforms.remove(self.transformer)
859 ip.input_splitter.python_line_transforms.remove(self.transformer)
857 ip.input_transformer_manager.python_line_transforms.remove(self.transformer)
860 ip.input_transformer_manager.python_line_transforms.remove(self.transformer)
858
861
859 def test_syntaxerror_input_transformer(self):
862 def test_syntaxerror_input_transformer(self):
860 with tt.AssertPrints('1234'):
863 with tt.AssertPrints('1234'):
861 ip.run_cell('1234')
864 ip.run_cell('1234')
862 with tt.AssertPrints('SyntaxError: invalid syntax'):
865 with tt.AssertPrints('SyntaxError: invalid syntax'):
863 ip.run_cell('1 2 3') # plain python syntax error
866 ip.run_cell('1 2 3') # plain python syntax error
864 with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
867 with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
865 ip.run_cell('2345 # syntaxerror') # input transformer syntax error
868 ip.run_cell('2345 # syntaxerror') # input transformer syntax error
866 with tt.AssertPrints('3456'):
869 with tt.AssertPrints('3456'):
867 ip.run_cell('3456')
870 ip.run_cell('3456')
868
871
869
872
870
873
871 def test_warning_suppression():
874 def test_warning_suppression():
872 ip.run_cell("import warnings")
875 ip.run_cell("import warnings")
873 try:
876 try:
874 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
877 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
875 ip.run_cell("warnings.warn('asdf')")
878 ip.run_cell("warnings.warn('asdf')")
876 # Here's the real test -- if we run that again, we should get the
879 # Here's the real test -- if we run that again, we should get the
877 # warning again. Traditionally, each warning was only issued once per
880 # warning again. Traditionally, each warning was only issued once per
878 # IPython session (approximately), even if the user typed in new and
881 # IPython session (approximately), even if the user typed in new and
879 # different code that should have also triggered the warning, leading
882 # different code that should have also triggered the warning, leading
880 # to much confusion.
883 # to much confusion.
881 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
884 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
882 ip.run_cell("warnings.warn('asdf')")
885 ip.run_cell("warnings.warn('asdf')")
883 finally:
886 finally:
884 ip.run_cell("del warnings")
887 ip.run_cell("del warnings")
General Comments 0
You need to be logged in to leave comments. Login now