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