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