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