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