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