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