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