##// END OF EJS Templates
Stop duplicating `nt.assert*` in `IPython.testing.tools`.
Bradley M. Froehle -
Show More
@@ -1,764 +1,764 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for various magic functions.
3 3
4 4 Needs to be run by nose (to make ipython session available).
5 5 """
6 6 from __future__ import absolute_import
7 7
8 8 #-----------------------------------------------------------------------------
9 9 # Imports
10 10 #-----------------------------------------------------------------------------
11 11
12 12 import io
13 13 import os
14 14 import sys
15 15 from StringIO import StringIO
16 16 from unittest import TestCase
17 17
18 18 try:
19 19 from importlib import invalidate_caches # Required from Python 3.3
20 20 except ImportError:
21 21 def invalidate_caches():
22 22 pass
23 23
24 24 import nose.tools as nt
25 25
26 26 from IPython.core import magic
27 27 from IPython.core.magic import (Magics, magics_class, line_magic,
28 28 cell_magic, line_cell_magic,
29 29 register_line_magic, register_cell_magic,
30 30 register_line_cell_magic)
31 31 from IPython.core.magics import execution, script
32 32 from IPython.nbformat.v3.tests.nbexamples import nb0
33 33 from IPython.nbformat import current
34 34 from IPython.testing import decorators as dec
35 35 from IPython.testing import tools as tt
36 36 from IPython.utils import py3compat
37 37 from IPython.utils.tempdir import TemporaryDirectory
38 38 from IPython.utils.process import find_cmd
39 39
40 40 #-----------------------------------------------------------------------------
41 41 # Test functions begin
42 42 #-----------------------------------------------------------------------------
43 43
44 44 @magic.magics_class
45 45 class DummyMagics(magic.Magics): pass
46 46
47 47 def test_rehashx():
48 48 # clear up everything
49 49 _ip = get_ipython()
50 50 _ip.alias_manager.alias_table.clear()
51 51 del _ip.db['syscmdlist']
52 52
53 53 _ip.magic('rehashx')
54 54 # Practically ALL ipython development systems will have more than 10 aliases
55 55
56 56 yield (nt.assert_true, len(_ip.alias_manager.alias_table) > 10)
57 57 for key, val in _ip.alias_manager.alias_table.iteritems():
58 58 # we must strip dots from alias names
59 59 nt.assert_true('.' not in key)
60 60
61 61 # rehashx must fill up syscmdlist
62 62 scoms = _ip.db['syscmdlist']
63 63 yield (nt.assert_true, len(scoms) > 10)
64 64
65 65
66 66 def test_magic_parse_options():
67 67 """Test that we don't mangle paths when parsing magic options."""
68 68 ip = get_ipython()
69 69 path = 'c:\\x'
70 70 m = DummyMagics(ip)
71 71 opts = m.parse_options('-f %s' % path,'f:')[0]
72 72 # argv splitting is os-dependent
73 73 if os.name == 'posix':
74 74 expected = 'c:x'
75 75 else:
76 76 expected = path
77 77 nt.assert_equal(opts['f'], expected)
78 78
79 79 def test_magic_parse_long_options():
80 80 """Magic.parse_options can handle --foo=bar long options"""
81 81 ip = get_ipython()
82 82 m = DummyMagics(ip)
83 83 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
84 84 nt.assert_true('foo' in opts)
85 85 nt.assert_true('bar' in opts)
86 86 nt.assert_true(opts['bar'], "bubble")
87 87
88 88
89 89 @dec.skip_without('sqlite3')
90 90 def doctest_hist_f():
91 91 """Test %hist -f with temporary filename.
92 92
93 93 In [9]: import tempfile
94 94
95 95 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
96 96
97 97 In [11]: %hist -nl -f $tfile 3
98 98
99 99 In [13]: import os; os.unlink(tfile)
100 100 """
101 101
102 102
103 103 @dec.skip_without('sqlite3')
104 104 def doctest_hist_r():
105 105 """Test %hist -r
106 106
107 107 XXX - This test is not recording the output correctly. For some reason, in
108 108 testing mode the raw history isn't getting populated. No idea why.
109 109 Disabling the output checking for now, though at least we do run it.
110 110
111 111 In [1]: 'hist' in _ip.lsmagic()
112 112 Out[1]: True
113 113
114 114 In [2]: x=1
115 115
116 116 In [3]: %hist -rl 2
117 117 x=1 # random
118 118 %hist -r 2
119 119 """
120 120
121 121
122 122 @dec.skip_without('sqlite3')
123 123 def doctest_hist_op():
124 124 """Test %hist -op
125 125
126 126 In [1]: class b(float):
127 127 ...: pass
128 128 ...:
129 129
130 130 In [2]: class s(object):
131 131 ...: def __str__(self):
132 132 ...: return 's'
133 133 ...:
134 134
135 135 In [3]:
136 136
137 137 In [4]: class r(b):
138 138 ...: def __repr__(self):
139 139 ...: return 'r'
140 140 ...:
141 141
142 142 In [5]: class sr(s,r): pass
143 143 ...:
144 144
145 145 In [6]:
146 146
147 147 In [7]: bb=b()
148 148
149 149 In [8]: ss=s()
150 150
151 151 In [9]: rr=r()
152 152
153 153 In [10]: ssrr=sr()
154 154
155 155 In [11]: 4.5
156 156 Out[11]: 4.5
157 157
158 158 In [12]: str(ss)
159 159 Out[12]: 's'
160 160
161 161 In [13]:
162 162
163 163 In [14]: %hist -op
164 164 >>> class b:
165 165 ... pass
166 166 ...
167 167 >>> class s(b):
168 168 ... def __str__(self):
169 169 ... return 's'
170 170 ...
171 171 >>>
172 172 >>> class r(b):
173 173 ... def __repr__(self):
174 174 ... return 'r'
175 175 ...
176 176 >>> class sr(s,r): pass
177 177 >>>
178 178 >>> bb=b()
179 179 >>> ss=s()
180 180 >>> rr=r()
181 181 >>> ssrr=sr()
182 182 >>> 4.5
183 183 4.5
184 184 >>> str(ss)
185 185 's'
186 186 >>>
187 187 """
188 188
189 189
190 190 @dec.skip_without('sqlite3')
191 191 def test_macro():
192 192 ip = get_ipython()
193 193 ip.history_manager.reset() # Clear any existing history.
194 194 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
195 195 for i, cmd in enumerate(cmds, start=1):
196 196 ip.history_manager.store_inputs(i, cmd)
197 197 ip.magic("macro test 1-3")
198 198 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
199 199
200 200 # List macros.
201 201 assert "test" in ip.magic("macro")
202 202
203 203
204 204 @dec.skip_without('sqlite3')
205 205 def test_macro_run():
206 206 """Test that we can run a multi-line macro successfully."""
207 207 ip = get_ipython()
208 208 ip.history_manager.reset()
209 209 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
210 210 "%macro test 2-3"]
211 211 for cmd in cmds:
212 212 ip.run_cell(cmd, store_history=True)
213 213 nt.assert_equal(ip.user_ns["test"].value,
214 214 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
215 215 with tt.AssertPrints("12"):
216 216 ip.run_cell("test")
217 217 with tt.AssertPrints("13"):
218 218 ip.run_cell("test")
219 219
220 220
221 221 @dec.skipif_not_numpy
222 222 def test_numpy_reset_array_undec():
223 223 "Test '%reset array' functionality"
224 224 _ip.ex('import numpy as np')
225 225 _ip.ex('a = np.empty(2)')
226 226 yield (nt.assert_true, 'a' in _ip.user_ns)
227 227 _ip.magic('reset -f array')
228 228 yield (nt.assert_false, 'a' in _ip.user_ns)
229 229
230 230 def test_reset_out():
231 231 "Test '%reset out' magic"
232 232 _ip.run_cell("parrot = 'dead'", store_history=True)
233 233 # test '%reset -f out', make an Out prompt
234 234 _ip.run_cell("parrot", store_history=True)
235 235 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
236 236 _ip.magic('reset -f out')
237 237 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
238 238 nt.assert_true(len(_ip.user_ns['Out']) == 0)
239 239
240 240 def test_reset_in():
241 241 "Test '%reset in' magic"
242 242 # test '%reset -f in'
243 243 _ip.run_cell("parrot", store_history=True)
244 244 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
245 245 _ip.magic('%reset -f in')
246 246 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
247 247 nt.assert_true(len(set(_ip.user_ns['In'])) == 1)
248 248
249 249 def test_reset_dhist():
250 250 "Test '%reset dhist' magic"
251 251 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
252 252 _ip.magic('cd ' + os.path.dirname(nt.__file__))
253 253 _ip.magic('cd -')
254 254 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
255 255 _ip.magic('reset -f dhist')
256 256 nt.assert_true(len(_ip.user_ns['_dh']) == 0)
257 257 _ip.run_cell("_dh = [d for d in tmp]") #restore
258 258
259 259 def test_reset_in_length():
260 260 "Test that '%reset in' preserves In[] length"
261 261 _ip.run_cell("print 'foo'")
262 262 _ip.run_cell("reset -f in")
263 263 nt.assert_true(len(_ip.user_ns['In']) == _ip.displayhook.prompt_count+1)
264 264
265 265 def test_time():
266 266 _ip.magic('time None')
267 267
268 268 def test_tb_syntaxerror():
269 269 """test %tb after a SyntaxError"""
270 270 ip = get_ipython()
271 271 ip.run_cell("for")
272 272
273 273 # trap and validate stdout
274 274 save_stdout = sys.stdout
275 275 try:
276 276 sys.stdout = StringIO()
277 277 ip.run_cell("%tb")
278 278 out = sys.stdout.getvalue()
279 279 finally:
280 280 sys.stdout = save_stdout
281 281 # trim output, and only check the last line
282 282 last_line = out.rstrip().splitlines()[-1].strip()
283 283 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
284 284
285 285
286 286 @py3compat.doctest_refactor_print
287 287 def doctest_time():
288 288 """
289 289 In [10]: %time None
290 290 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
291 291 Wall time: 0.00 s
292 292
293 293 In [11]: def f(kmjy):
294 294 ....: %time print 2*kmjy
295 295
296 296 In [12]: f(3)
297 297 6
298 298 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
299 299 Wall time: 0.00 s
300 300 """
301 301
302 302
303 303 def test_doctest_mode():
304 304 "Toggle doctest_mode twice, it should be a no-op and run without error"
305 305 _ip.magic('doctest_mode')
306 306 _ip.magic('doctest_mode')
307 307
308 308
309 309 def test_parse_options():
310 310 """Tests for basic options parsing in magics."""
311 311 # These are only the most minimal of tests, more should be added later. At
312 312 # the very least we check that basic text/unicode calls work OK.
313 313 m = DummyMagics(_ip)
314 314 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
315 315 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
316 316
317 317
318 318 def test_dirops():
319 319 """Test various directory handling operations."""
320 320 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
321 321 curpath = os.getcwdu
322 322 startdir = os.getcwdu()
323 323 ipdir = os.path.realpath(_ip.ipython_dir)
324 324 try:
325 325 _ip.magic('cd "%s"' % ipdir)
326 326 nt.assert_equal(curpath(), ipdir)
327 327 _ip.magic('cd -')
328 328 nt.assert_equal(curpath(), startdir)
329 329 _ip.magic('pushd "%s"' % ipdir)
330 330 nt.assert_equal(curpath(), ipdir)
331 331 _ip.magic('popd')
332 332 nt.assert_equal(curpath(), startdir)
333 333 finally:
334 334 os.chdir(startdir)
335 335
336 336
337 337 def test_xmode():
338 338 # Calling xmode three times should be a no-op
339 339 xmode = _ip.InteractiveTB.mode
340 340 for i in range(3):
341 341 _ip.magic("xmode")
342 342 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
343 343
344 344 def test_reset_hard():
345 345 monitor = []
346 346 class A(object):
347 347 def __del__(self):
348 348 monitor.append(1)
349 349 def __repr__(self):
350 350 return "<A instance>"
351 351
352 352 _ip.user_ns["a"] = A()
353 353 _ip.run_cell("a")
354 354
355 355 nt.assert_equal(monitor, [])
356 356 _ip.magic("reset -f")
357 357 nt.assert_equal(monitor, [1])
358 358
359 359 class TestXdel(tt.TempFileMixin):
360 360 def test_xdel(self):
361 361 """Test that references from %run are cleared by xdel."""
362 362 src = ("class A(object):\n"
363 363 " monitor = []\n"
364 364 " def __del__(self):\n"
365 365 " self.monitor.append(1)\n"
366 366 "a = A()\n")
367 367 self.mktmp(src)
368 368 # %run creates some hidden references...
369 369 _ip.magic("run %s" % self.fname)
370 370 # ... as does the displayhook.
371 371 _ip.run_cell("a")
372 372
373 373 monitor = _ip.user_ns["A"].monitor
374 374 nt.assert_equal(monitor, [])
375 375
376 376 _ip.magic("xdel a")
377 377
378 378 # Check that a's __del__ method has been called.
379 379 nt.assert_equal(monitor, [1])
380 380
381 381 def doctest_who():
382 382 """doctest for %who
383 383
384 384 In [1]: %reset -f
385 385
386 386 In [2]: alpha = 123
387 387
388 388 In [3]: beta = 'beta'
389 389
390 390 In [4]: %who int
391 391 alpha
392 392
393 393 In [5]: %who str
394 394 beta
395 395
396 396 In [6]: %whos
397 397 Variable Type Data/Info
398 398 ----------------------------
399 399 alpha int 123
400 400 beta str beta
401 401
402 402 In [7]: %who_ls
403 403 Out[7]: ['alpha', 'beta']
404 404 """
405 405
406 406 def test_whos():
407 407 """Check that whos is protected against objects where repr() fails."""
408 408 class A(object):
409 409 def __repr__(self):
410 410 raise Exception()
411 411 _ip.user_ns['a'] = A()
412 412 _ip.magic("whos")
413 413
414 414 @py3compat.u_format
415 415 def doctest_precision():
416 416 """doctest for %precision
417 417
418 418 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
419 419
420 420 In [2]: %precision 5
421 421 Out[2]: {u}'%.5f'
422 422
423 423 In [3]: f.float_format
424 424 Out[3]: {u}'%.5f'
425 425
426 426 In [4]: %precision %e
427 427 Out[4]: {u}'%e'
428 428
429 429 In [5]: f(3.1415927)
430 430 Out[5]: {u}'3.141593e+00'
431 431 """
432 432
433 433 def test_psearch():
434 434 with tt.AssertPrints("dict.fromkeys"):
435 435 _ip.run_cell("dict.fr*?")
436 436
437 437 def test_timeit_shlex():
438 438 """test shlex issues with timeit (#1109)"""
439 439 _ip.ex("def f(*a,**kw): pass")
440 440 _ip.magic('timeit -n1 "this is a bug".count(" ")')
441 441 _ip.magic('timeit -r1 -n1 f(" ", 1)')
442 442 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
443 443 _ip.magic('timeit -r1 -n1 ("a " + "b")')
444 444 _ip.magic('timeit -r1 -n1 f("a " + "b")')
445 445 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
446 446
447 447
448 448 def test_timeit_arguments():
449 449 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
450 450 _ip.magic("timeit ('#')")
451 451
452 452
453 453 def test_timeit_special_syntax():
454 454 "Test %%timeit with IPython special syntax"
455 455 from IPython.core.magic import register_line_magic
456 456
457 457 @register_line_magic
458 458 def lmagic(line):
459 459 ip = get_ipython()
460 460 ip.user_ns['lmagic_out'] = line
461 461
462 462 # line mode test
463 463 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
464 464 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
465 465 # cell mode test
466 466 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
467 467 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
468 468
469 469
470 470 @dec.skipif(execution.profile is None)
471 471 def test_prun_quotes():
472 472 "Test that prun does not clobber string escapes (GH #1302)"
473 473 _ip.magic(r"prun -q x = '\t'")
474 474 nt.assert_equal(_ip.user_ns['x'], '\t')
475 475
476 476 def test_extension():
477 477 tmpdir = TemporaryDirectory()
478 478 orig_ipython_dir = _ip.ipython_dir
479 479 try:
480 480 _ip.ipython_dir = tmpdir.name
481 481 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
482 482 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
483 483 _ip.magic("install_ext %s" % url)
484 484 _ip.user_ns.pop('arq', None)
485 485 invalidate_caches() # Clear import caches
486 486 _ip.magic("load_ext daft_extension")
487 tt.assert_equal(_ip.user_ns['arq'], 185)
487 nt.assert_equal(_ip.user_ns['arq'], 185)
488 488 _ip.magic("unload_ext daft_extension")
489 489 assert 'arq' not in _ip.user_ns
490 490 finally:
491 491 _ip.ipython_dir = orig_ipython_dir
492 492 tmpdir.cleanup()
493 493
494 494 def test_notebook_export_json():
495 495 with TemporaryDirectory() as td:
496 496 outfile = os.path.join(td, "nb.ipynb")
497 497 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
498 498 _ip.magic("notebook -e %s" % outfile)
499 499
500 500 def test_notebook_export_py():
501 501 with TemporaryDirectory() as td:
502 502 outfile = os.path.join(td, "nb.py")
503 503 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
504 504 _ip.magic("notebook -e %s" % outfile)
505 505
506 506 def test_notebook_reformat_py():
507 507 with TemporaryDirectory() as td:
508 508 infile = os.path.join(td, "nb.ipynb")
509 509 with io.open(infile, 'w', encoding='utf-8') as f:
510 510 current.write(nb0, f, 'json')
511 511
512 512 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
513 513 _ip.magic("notebook -f py %s" % infile)
514 514
515 515 def test_notebook_reformat_json():
516 516 with TemporaryDirectory() as td:
517 517 infile = os.path.join(td, "nb.py")
518 518 with io.open(infile, 'w', encoding='utf-8') as f:
519 519 current.write(nb0, f, 'py')
520 520
521 521 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
522 522 _ip.magic("notebook -f ipynb %s" % infile)
523 523 _ip.magic("notebook -f json %s" % infile)
524 524
525 525 def test_env():
526 526 env = _ip.magic("env")
527 527 assert isinstance(env, dict), type(env)
528 528
529 529
530 530 class CellMagicTestCase(TestCase):
531 531
532 532 def check_ident(self, magic):
533 533 # Manually called, we get the result
534 534 out = _ip.run_cell_magic(magic, 'a', 'b')
535 535 nt.assert_equal(out, ('a','b'))
536 536 # Via run_cell, it goes into the user's namespace via displayhook
537 537 _ip.run_cell('%%' + magic +' c\nd')
538 538 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
539 539
540 540 def test_cell_magic_func_deco(self):
541 541 "Cell magic using simple decorator"
542 542 @register_cell_magic
543 543 def cellm(line, cell):
544 544 return line, cell
545 545
546 546 self.check_ident('cellm')
547 547
548 548 def test_cell_magic_reg(self):
549 549 "Cell magic manually registered"
550 550 def cellm(line, cell):
551 551 return line, cell
552 552
553 553 _ip.register_magic_function(cellm, 'cell', 'cellm2')
554 554 self.check_ident('cellm2')
555 555
556 556 def test_cell_magic_class(self):
557 557 "Cell magics declared via a class"
558 558 @magics_class
559 559 class MyMagics(Magics):
560 560
561 561 @cell_magic
562 562 def cellm3(self, line, cell):
563 563 return line, cell
564 564
565 565 _ip.register_magics(MyMagics)
566 566 self.check_ident('cellm3')
567 567
568 568 def test_cell_magic_class2(self):
569 569 "Cell magics declared via a class, #2"
570 570 @magics_class
571 571 class MyMagics2(Magics):
572 572
573 573 @cell_magic('cellm4')
574 574 def cellm33(self, line, cell):
575 575 return line, cell
576 576
577 577 _ip.register_magics(MyMagics2)
578 578 self.check_ident('cellm4')
579 579 # Check that nothing is registered as 'cellm33'
580 580 c33 = _ip.find_cell_magic('cellm33')
581 581 nt.assert_equal(c33, None)
582 582
583 583 def test_file():
584 584 """Basic %%file"""
585 585 ip = get_ipython()
586 586 with TemporaryDirectory() as td:
587 587 fname = os.path.join(td, 'file1')
588 588 ip.run_cell_magic("file", fname, u'\n'.join([
589 589 'line1',
590 590 'line2',
591 591 ]))
592 592 with open(fname) as f:
593 593 s = f.read()
594 594 nt.assert_in('line1\n', s)
595 595 nt.assert_in('line2', s)
596 596
597 597 def test_file_unicode():
598 598 """%%file with unicode cell"""
599 599 ip = get_ipython()
600 600 with TemporaryDirectory() as td:
601 601 fname = os.path.join(td, 'file1')
602 602 ip.run_cell_magic("file", fname, u'\n'.join([
603 603 u'linΓ©1',
604 604 u'linΓ©2',
605 605 ]))
606 606 with io.open(fname, encoding='utf-8') as f:
607 607 s = f.read()
608 608 nt.assert_in(u'linΓ©1\n', s)
609 609 nt.assert_in(u'linΓ©2', s)
610 610
611 611 def test_file_amend():
612 612 """%%file -a amends files"""
613 613 ip = get_ipython()
614 614 with TemporaryDirectory() as td:
615 615 fname = os.path.join(td, 'file2')
616 616 ip.run_cell_magic("file", fname, u'\n'.join([
617 617 'line1',
618 618 'line2',
619 619 ]))
620 620 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
621 621 'line3',
622 622 'line4',
623 623 ]))
624 624 with open(fname) as f:
625 625 s = f.read()
626 626 nt.assert_in('line1\n', s)
627 627 nt.assert_in('line3\n', s)
628 628
629 629
630 630 def test_script_config():
631 631 ip = get_ipython()
632 632 ip.config.ScriptMagics.script_magics = ['whoda']
633 633 sm = script.ScriptMagics(shell=ip)
634 634 nt.assert_in('whoda', sm.magics['cell'])
635 635
636 636 @dec.skip_win32
637 637 def test_script_out():
638 638 ip = get_ipython()
639 639 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
640 640 nt.assert_equal(ip.user_ns['output'], 'hi\n')
641 641
642 642 @dec.skip_win32
643 643 def test_script_err():
644 644 ip = get_ipython()
645 645 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
646 646 nt.assert_equal(ip.user_ns['error'], 'hello\n')
647 647
648 648 @dec.skip_win32
649 649 def test_script_out_err():
650 650 ip = get_ipython()
651 651 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
652 652 nt.assert_equal(ip.user_ns['output'], 'hi\n')
653 653 nt.assert_equal(ip.user_ns['error'], 'hello\n')
654 654
655 655 @dec.skip_win32
656 656 def test_script_bg_out():
657 657 ip = get_ipython()
658 658 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
659 659 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
660 660
661 661 @dec.skip_win32
662 662 def test_script_bg_err():
663 663 ip = get_ipython()
664 664 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
665 665 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
666 666
667 667 @dec.skip_win32
668 668 def test_script_bg_out_err():
669 669 ip = get_ipython()
670 670 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
671 671 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
672 672 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
673 673
674 674 def test_script_defaults():
675 675 ip = get_ipython()
676 676 for cmd in ['sh', 'bash', 'perl', 'ruby']:
677 677 try:
678 678 find_cmd(cmd)
679 679 except Exception:
680 680 pass
681 681 else:
682 682 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
683 683
684 684
685 685 @magics_class
686 686 class FooFoo(Magics):
687 687 """class with both %foo and %%foo magics"""
688 688 @line_magic('foo')
689 689 def line_foo(self, line):
690 690 "I am line foo"
691 691 pass
692 692
693 693 @cell_magic("foo")
694 694 def cell_foo(self, line, cell):
695 695 "I am cell foo, not line foo"
696 696 pass
697 697
698 698 def test_line_cell_info():
699 699 """%%foo and %foo magics are distinguishable to inspect"""
700 700 ip = get_ipython()
701 701 ip.magics_manager.register(FooFoo)
702 702 oinfo = ip.object_inspect('foo')
703 703 nt.assert_true(oinfo['found'])
704 704 nt.assert_true(oinfo['ismagic'])
705 705
706 706 oinfo = ip.object_inspect('%%foo')
707 707 nt.assert_true(oinfo['found'])
708 708 nt.assert_true(oinfo['ismagic'])
709 709 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
710 710
711 711 oinfo = ip.object_inspect('%foo')
712 712 nt.assert_true(oinfo['found'])
713 713 nt.assert_true(oinfo['ismagic'])
714 714 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
715 715
716 716 def test_multiple_magics():
717 717 ip = get_ipython()
718 718 foo1 = FooFoo(ip)
719 719 foo2 = FooFoo(ip)
720 720 mm = ip.magics_manager
721 721 mm.register(foo1)
722 722 nt.assert_true(mm.magics['line']['foo'].im_self is foo1)
723 723 mm.register(foo2)
724 724 nt.assert_true(mm.magics['line']['foo'].im_self is foo2)
725 725
726 726 def test_alias_magic():
727 727 """Test %alias_magic."""
728 728 ip = get_ipython()
729 729 mm = ip.magics_manager
730 730
731 731 # Basic operation: both cell and line magics are created, if possible.
732 732 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
733 733 nt.assert_true('timeit_alias' in mm.magics['line'])
734 734 nt.assert_true('timeit_alias' in mm.magics['cell'])
735 735
736 736 # --cell is specified, line magic not created.
737 737 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
738 738 nt.assert_false('timeit_cell_alias' in mm.magics['line'])
739 739 nt.assert_true('timeit_cell_alias' in mm.magics['cell'])
740 740
741 741 # Test that line alias is created successfully.
742 742 ip.run_line_magic('alias_magic', '--line env_alias env')
743 743 nt.assert_equal(ip.run_line_magic('env', ''),
744 744 ip.run_line_magic('env_alias', ''))
745 745
746 746 def test_save():
747 747 """Test %save."""
748 748 ip = get_ipython()
749 749 ip.history_manager.reset() # Clear any existing history.
750 750 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
751 751 for i, cmd in enumerate(cmds, start=1):
752 752 ip.history_manager.store_inputs(i, cmd)
753 753 with TemporaryDirectory() as tmpdir:
754 754 file = os.path.join(tmpdir, "testsave.py")
755 755 ip.run_line_magic("save", "%s 1-10" % file)
756 756 with open(file) as f:
757 757 content = f.read()
758 758 nt.assert_equal(content.count(cmds[0]), 1)
759 759 nt.assert_true('coding: utf-8' in content)
760 760 ip.run_line_magic("save", "-a %s 1-10" % file)
761 761 with open(file) as f:
762 762 content = f.read()
763 763 nt.assert_equal(content.count(cmds[0]), 2)
764 764 nt.assert_true('coding: utf-8' in content)
@@ -1,250 +1,250 b''
1 1 # encoding: utf-8
2 2 """Tests for code execution (%run and related), which is particularly tricky.
3 3
4 4 Because of how %run manages namespaces, and the fact that we are trying here to
5 5 verify subtle object deletion and reference counting issues, the %run tests
6 6 will be kept in this separate file. This makes it easier to aggregate in one
7 7 place the tricks needed to handle it; most other magics are much easier to test
8 8 and we do so in a common test_magic file.
9 9 """
10 10 from __future__ import absolute_import
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Imports
14 14 #-----------------------------------------------------------------------------
15 15
16 16 import os
17 17 import sys
18 18 import tempfile
19 19
20 20 import nose.tools as nt
21 21 from nose import SkipTest
22 22
23 23 from IPython.testing import decorators as dec
24 24 from IPython.testing import tools as tt
25 25 from IPython.utils import py3compat
26 26
27 27 #-----------------------------------------------------------------------------
28 28 # Test functions begin
29 29 #-----------------------------------------------------------------------------
30 30
31 31 def doctest_refbug():
32 32 """Very nasty problem with references held by multiple runs of a script.
33 33 See: https://github.com/ipython/ipython/issues/141
34 34
35 35 In [1]: _ip.clear_main_mod_cache()
36 36 # random
37 37
38 38 In [2]: %run refbug
39 39
40 40 In [3]: call_f()
41 41 lowercased: hello
42 42
43 43 In [4]: %run refbug
44 44
45 45 In [5]: call_f()
46 46 lowercased: hello
47 47 lowercased: hello
48 48 """
49 49
50 50
51 51 def doctest_run_builtins():
52 52 r"""Check that %run doesn't damage __builtins__.
53 53
54 54 In [1]: import tempfile
55 55
56 56 In [2]: bid1 = id(__builtins__)
57 57
58 58 In [3]: fname = tempfile.mkstemp('.py')[1]
59 59
60 60 In [3]: f = open(fname,'w')
61 61
62 62 In [4]: dummy= f.write('pass\n')
63 63
64 64 In [5]: f.flush()
65 65
66 66 In [6]: t1 = type(__builtins__)
67 67
68 68 In [7]: %run $fname
69 69
70 70 In [7]: f.close()
71 71
72 72 In [8]: bid2 = id(__builtins__)
73 73
74 74 In [9]: t2 = type(__builtins__)
75 75
76 76 In [10]: t1 == t2
77 77 Out[10]: True
78 78
79 79 In [10]: bid1 == bid2
80 80 Out[10]: True
81 81
82 82 In [12]: try:
83 83 ....: os.unlink(fname)
84 84 ....: except:
85 85 ....: pass
86 86 ....:
87 87 """
88 88
89 89 @py3compat.doctest_refactor_print
90 90 def doctest_reset_del():
91 91 """Test that resetting doesn't cause errors in __del__ methods.
92 92
93 93 In [2]: class A(object):
94 94 ...: def __del__(self):
95 95 ...: print str("Hi")
96 96 ...:
97 97
98 98 In [3]: a = A()
99 99
100 100 In [4]: get_ipython().reset()
101 101 Hi
102 102
103 103 In [5]: 1+1
104 104 Out[5]: 2
105 105 """
106 106
107 107 # For some tests, it will be handy to organize them in a class with a common
108 108 # setup that makes a temp file
109 109
110 110 class TestMagicRunPass(tt.TempFileMixin):
111 111
112 112 def setup(self):
113 113 """Make a valid python temp file."""
114 114 self.mktmp('pass\n')
115 115
116 116 def run_tmpfile(self):
117 117 _ip = get_ipython()
118 118 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
119 119 # See below and ticket https://bugs.launchpad.net/bugs/366353
120 120 _ip.magic('run %s' % self.fname)
121 121
122 122 def run_tmpfile_p(self):
123 123 _ip = get_ipython()
124 124 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
125 125 # See below and ticket https://bugs.launchpad.net/bugs/366353
126 126 _ip.magic('run -p %s' % self.fname)
127 127
128 128 def test_builtins_id(self):
129 129 """Check that %run doesn't damage __builtins__ """
130 130 _ip = get_ipython()
131 131 # Test that the id of __builtins__ is not modified by %run
132 132 bid1 = id(_ip.user_ns['__builtins__'])
133 133 self.run_tmpfile()
134 134 bid2 = id(_ip.user_ns['__builtins__'])
135 tt.assert_equals(bid1, bid2)
135 nt.assert_equal(bid1, bid2)
136 136
137 137 def test_builtins_type(self):
138 138 """Check that the type of __builtins__ doesn't change with %run.
139 139
140 140 However, the above could pass if __builtins__ was already modified to
141 141 be a dict (it should be a module) by a previous use of %run. So we
142 142 also check explicitly that it really is a module:
143 143 """
144 144 _ip = get_ipython()
145 145 self.run_tmpfile()
146 tt.assert_equals(type(_ip.user_ns['__builtins__']),type(sys))
146 nt.assert_equal(type(_ip.user_ns['__builtins__']),type(sys))
147 147
148 148 def test_prompts(self):
149 149 """Test that prompts correctly generate after %run"""
150 150 self.run_tmpfile()
151 151 _ip = get_ipython()
152 152 p2 = _ip.prompt_manager.render('in2').strip()
153 153 nt.assert_equal(p2[:3], '...')
154 154
155 155 def test_run_profile( self ):
156 156 """Test that the option -p, which invokes the profiler, do not
157 157 crash by invoking execfile"""
158 158 _ip = get_ipython()
159 159 self.run_tmpfile_p()
160 160
161 161
162 162 class TestMagicRunSimple(tt.TempFileMixin):
163 163
164 164 def test_simpledef(self):
165 165 """Test that simple class definitions work."""
166 166 src = ("class foo: pass\n"
167 167 "def f(): return foo()")
168 168 self.mktmp(src)
169 169 _ip.magic('run %s' % self.fname)
170 170 _ip.run_cell('t = isinstance(f(), foo)')
171 171 nt.assert_true(_ip.user_ns['t'])
172 172
173 173 def test_obj_del(self):
174 174 """Test that object's __del__ methods are called on exit."""
175 175 if sys.platform == 'win32':
176 176 try:
177 177 import win32api
178 178 except ImportError:
179 179 raise SkipTest("Test requires pywin32")
180 180 src = ("class A(object):\n"
181 181 " def __del__(self):\n"
182 182 " print 'object A deleted'\n"
183 183 "a = A()\n")
184 184 self.mktmp(py3compat.doctest_refactor_print(src))
185 185 if dec.module_not_available('sqlite3'):
186 186 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
187 187 else:
188 188 err = None
189 189 tt.ipexec_validate(self.fname, 'object A deleted', err)
190 190
191 191 @dec.skip_known_failure
192 192 def test_aggressive_namespace_cleanup(self):
193 193 """Test that namespace cleanup is not too aggressive GH-238
194 194
195 195 Returning from another run magic deletes the namespace"""
196 196 # see ticket https://github.com/ipython/ipython/issues/238
197 197 class secondtmp(tt.TempFileMixin): pass
198 198 empty = secondtmp()
199 199 empty.mktmp('')
200 200 src = ("ip = get_ipython()\n"
201 201 "for i in range(5):\n"
202 202 " try:\n"
203 203 " ip.magic('run %s')\n"
204 204 " except NameError as e:\n"
205 205 " print i;break\n" % empty.fname)
206 206 self.mktmp(py3compat.doctest_refactor_print(src))
207 207 _ip.magic('run %s' % self.fname)
208 208 _ip.run_cell('ip == get_ipython()')
209 tt.assert_equals(_ip.user_ns['i'], 5)
209 nt.assert_equal(_ip.user_ns['i'], 5)
210 210
211 211 @dec.skip_win32
212 212 def test_tclass(self):
213 213 mydir = os.path.dirname(__file__)
214 214 tc = os.path.join(mydir, 'tclass')
215 215 src = ("%%run '%s' C-first\n"
216 216 "%%run '%s' C-second\n"
217 217 "%%run '%s' C-third\n") % (tc, tc, tc)
218 218 self.mktmp(src, '.ipy')
219 219 out = """\
220 220 ARGV 1-: ['C-first']
221 221 ARGV 1-: ['C-second']
222 222 tclass.py: deleting object: C-first
223 223 ARGV 1-: ['C-third']
224 224 tclass.py: deleting object: C-second
225 225 tclass.py: deleting object: C-third
226 226 """
227 227 if dec.module_not_available('sqlite3'):
228 228 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
229 229 else:
230 230 err = None
231 231 tt.ipexec_validate(self.fname, out, err)
232 232
233 233 def test_run_i_after_reset(self):
234 234 """Check that %run -i still works after %reset (gh-693)"""
235 235 src = "yy = zz\n"
236 236 self.mktmp(src)
237 237 _ip.run_cell("zz = 23")
238 238 _ip.magic('run -i %s' % self.fname)
239 tt.assert_equals(_ip.user_ns['yy'], 23)
239 nt.assert_equal(_ip.user_ns['yy'], 23)
240 240 _ip.magic('reset -f')
241 241 _ip.run_cell("zz = 23")
242 242 _ip.magic('run -i %s' % self.fname)
243 tt.assert_equals(_ip.user_ns['yy'], 23)
243 nt.assert_equal(_ip.user_ns['yy'], 23)
244 244
245 245 def test_unicode(self):
246 246 """Check that files in odd encodings are accepted."""
247 247 mydir = os.path.dirname(__file__)
248 248 na = os.path.join(mydir, 'nonascii.py')
249 249 _ip.magic('run "%s"' % na)
250 tt.assert_equals(_ip.user_ns['u'], u'ΠŽΡ‚β„–Π€')
250 nt.assert_equal(_ip.user_ns['u'], u'ΠŽΡ‚β„–Π€')
@@ -1,392 +1,371 b''
1 1 """Generic testing tools.
2 2
3 In particular, this module exposes a set of top-level assert* functions that
4 can be used in place of nose.tools.assert* in method generators (the ones in
5 nose can not, at least as of nose 0.10.4).
6
7
8 3 Authors
9 4 -------
10 5 - Fernando Perez <Fernando.Perez@berkeley.edu>
11 6 """
12 7
13 8 from __future__ import absolute_import
14 9
15 10 #-----------------------------------------------------------------------------
16 11 # Copyright (C) 2009-2011 The IPython Development Team
17 12 #
18 13 # Distributed under the terms of the BSD License. The full license is in
19 14 # the file COPYING, distributed as part of this software.
20 15 #-----------------------------------------------------------------------------
21 16
22 17 #-----------------------------------------------------------------------------
23 18 # Imports
24 19 #-----------------------------------------------------------------------------
25 20
26 21 import os
27 22 import re
28 23 import sys
29 24 import tempfile
30 25
31 26 from contextlib import contextmanager
32 27 from io import StringIO
33 28
34 29 try:
35 30 # These tools are used by parts of the runtime, so we make the nose
36 31 # dependency optional at this point. Nose is a hard dependency to run the
37 32 # test suite, but NOT to use ipython itself.
38 33 import nose.tools as nt
39 34 has_nose = True
40 35 except ImportError:
41 36 has_nose = False
42 37
43 38 from IPython.config.loader import Config
44 39 from IPython.utils.process import find_cmd, getoutputerror
45 40 from IPython.utils.text import list_strings
46 41 from IPython.utils.io import temp_pyfile, Tee
47 42 from IPython.utils import py3compat
48 43 from IPython.utils.encoding import DEFAULT_ENCODING
49 44
50 45 from . import decorators as dec
51 46 from . import skipdoctest
52 47
53 48 #-----------------------------------------------------------------------------
54 # Globals
55 #-----------------------------------------------------------------------------
56
57 # Make a bunch of nose.tools assert wrappers that can be used in test
58 # generators. This will expose an assert* function for each one in nose.tools.
59
60 _tpl = """
61 def %(name)s(*a,**kw):
62 return nt.%(name)s(*a,**kw)
63 """
64
65 if has_nose:
66 for _x in [a for a in dir(nt) if a.startswith('assert')]:
67 exec _tpl % dict(name=_x)
68
69 #-----------------------------------------------------------------------------
70 49 # Functions and classes
71 50 #-----------------------------------------------------------------------------
72 51
73 52 # The docstring for full_path doctests differently on win32 (different path
74 53 # separator) so just skip the doctest there. The example remains informative.
75 54 doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco
76 55
77 56 @doctest_deco
78 57 def full_path(startPath,files):
79 58 """Make full paths for all the listed files, based on startPath.
80 59
81 60 Only the base part of startPath is kept, since this routine is typically
82 61 used with a script's __file__ variable as startPath. The base of startPath
83 62 is then prepended to all the listed files, forming the output list.
84 63
85 64 Parameters
86 65 ----------
87 66 startPath : string
88 67 Initial path to use as the base for the results. This path is split
89 68 using os.path.split() and only its first component is kept.
90 69
91 70 files : string or list
92 71 One or more files.
93 72
94 73 Examples
95 74 --------
96 75
97 76 >>> full_path('/foo/bar.py',['a.txt','b.txt'])
98 77 ['/foo/a.txt', '/foo/b.txt']
99 78
100 79 >>> full_path('/foo',['a.txt','b.txt'])
101 80 ['/a.txt', '/b.txt']
102 81
103 82 If a single file is given, the output is still a list:
104 83 >>> full_path('/foo','a.txt')
105 84 ['/a.txt']
106 85 """
107 86
108 87 files = list_strings(files)
109 88 base = os.path.split(startPath)[0]
110 89 return [ os.path.join(base,f) for f in files ]
111 90
112 91
113 92 def parse_test_output(txt):
114 93 """Parse the output of a test run and return errors, failures.
115 94
116 95 Parameters
117 96 ----------
118 97 txt : str
119 98 Text output of a test run, assumed to contain a line of one of the
120 99 following forms::
121 100 'FAILED (errors=1)'
122 101 'FAILED (failures=1)'
123 102 'FAILED (errors=1, failures=1)'
124 103
125 104 Returns
126 105 -------
127 106 nerr, nfail: number of errors and failures.
128 107 """
129 108
130 109 err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE)
131 110 if err_m:
132 111 nerr = int(err_m.group(1))
133 112 nfail = 0
134 113 return nerr, nfail
135 114
136 115 fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE)
137 116 if fail_m:
138 117 nerr = 0
139 118 nfail = int(fail_m.group(1))
140 119 return nerr, nfail
141 120
142 121 both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt,
143 122 re.MULTILINE)
144 123 if both_m:
145 124 nerr = int(both_m.group(1))
146 125 nfail = int(both_m.group(2))
147 126 return nerr, nfail
148 127
149 128 # If the input didn't match any of these forms, assume no error/failures
150 129 return 0, 0
151 130
152 131
153 132 # So nose doesn't think this is a test
154 133 parse_test_output.__test__ = False
155 134
156 135
157 136 def default_argv():
158 137 """Return a valid default argv for creating testing instances of ipython"""
159 138
160 139 return ['--quick', # so no config file is loaded
161 140 # Other defaults to minimize side effects on stdout
162 141 '--colors=NoColor', '--no-term-title','--no-banner',
163 142 '--autocall=0']
164 143
165 144
166 145 def default_config():
167 146 """Return a config object with good defaults for testing."""
168 147 config = Config()
169 148 config.TerminalInteractiveShell.colors = 'NoColor'
170 149 config.TerminalTerminalInteractiveShell.term_title = False,
171 150 config.TerminalInteractiveShell.autocall = 0
172 151 config.HistoryManager.hist_file = tempfile.mktemp(u'test_hist.sqlite')
173 152 config.HistoryManager.db_cache_size = 10000
174 153 return config
175 154
176 155
177 156 def ipexec(fname, options=None):
178 157 """Utility to call 'ipython filename'.
179 158
180 159 Starts IPython witha minimal and safe configuration to make startup as fast
181 160 as possible.
182 161
183 162 Note that this starts IPython in a subprocess!
184 163
185 164 Parameters
186 165 ----------
187 166 fname : str
188 167 Name of file to be executed (should have .py or .ipy extension).
189 168
190 169 options : optional, list
191 170 Extra command-line flags to be passed to IPython.
192 171
193 172 Returns
194 173 -------
195 174 (stdout, stderr) of ipython subprocess.
196 175 """
197 176 if options is None: options = []
198 177
199 178 # For these subprocess calls, eliminate all prompt printing so we only see
200 179 # output from script execution
201 180 prompt_opts = [ '--PromptManager.in_template=""',
202 181 '--PromptManager.in2_template=""',
203 182 '--PromptManager.out_template=""'
204 183 ]
205 184 cmdargs = ' '.join(default_argv() + prompt_opts + options)
206 185
207 186 _ip = get_ipython()
208 187 test_dir = os.path.dirname(__file__)
209 188
210 189 ipython_cmd = find_cmd('ipython3' if py3compat.PY3 else 'ipython')
211 190 # Absolute path for filename
212 191 full_fname = os.path.join(test_dir, fname)
213 192 full_cmd = '%s %s %s' % (ipython_cmd, cmdargs, full_fname)
214 193 #print >> sys.stderr, 'FULL CMD:', full_cmd # dbg
215 194 out, err = getoutputerror(full_cmd)
216 195 # `import readline` causes 'ESC[?1034h' to be output sometimes,
217 196 # so strip that out before doing comparisons
218 197 if out:
219 198 out = re.sub(r'\x1b\[[^h]+h', '', out)
220 199 return out, err
221 200
222 201
223 202 def ipexec_validate(fname, expected_out, expected_err='',
224 203 options=None):
225 204 """Utility to call 'ipython filename' and validate output/error.
226 205
227 206 This function raises an AssertionError if the validation fails.
228 207
229 208 Note that this starts IPython in a subprocess!
230 209
231 210 Parameters
232 211 ----------
233 212 fname : str
234 213 Name of the file to be executed (should have .py or .ipy extension).
235 214
236 215 expected_out : str
237 216 Expected stdout of the process.
238 217
239 218 expected_err : optional, str
240 219 Expected stderr of the process.
241 220
242 221 options : optional, list
243 222 Extra command-line flags to be passed to IPython.
244 223
245 224 Returns
246 225 -------
247 226 None
248 227 """
249 228
250 229 import nose.tools as nt
251 230
252 231 out, err = ipexec(fname, options)
253 232 #print 'OUT', out # dbg
254 233 #print 'ERR', err # dbg
255 234 # If there are any errors, we must check those befor stdout, as they may be
256 235 # more informative than simply having an empty stdout.
257 236 if err:
258 237 if expected_err:
259 238 nt.assert_equal(err.strip(), expected_err.strip())
260 239 else:
261 240 raise ValueError('Running file %r produced error: %r' %
262 241 (fname, err))
263 242 # If no errors or output on stderr was expected, match stdout
264 243 nt.assert_equal(out.strip(), expected_out.strip())
265 244
266 245
267 246 class TempFileMixin(object):
268 247 """Utility class to create temporary Python/IPython files.
269 248
270 249 Meant as a mixin class for test cases."""
271 250
272 251 def mktmp(self, src, ext='.py'):
273 252 """Make a valid python temp file."""
274 253 fname, f = temp_pyfile(src, ext)
275 254 self.tmpfile = f
276 255 self.fname = fname
277 256
278 257 def tearDown(self):
279 258 if hasattr(self, 'tmpfile'):
280 259 # If the tmpfile wasn't made because of skipped tests, like in
281 260 # win32, there's nothing to cleanup.
282 261 self.tmpfile.close()
283 262 try:
284 263 os.unlink(self.fname)
285 264 except:
286 265 # On Windows, even though we close the file, we still can't
287 266 # delete it. I have no clue why
288 267 pass
289 268
290 269 pair_fail_msg = ("Testing {0}\n\n"
291 270 "In:\n"
292 271 " {1!r}\n"
293 272 "Expected:\n"
294 273 " {2!r}\n"
295 274 "Got:\n"
296 275 " {3!r}\n")
297 276 def check_pairs(func, pairs):
298 277 """Utility function for the common case of checking a function with a
299 278 sequence of input/output pairs.
300 279
301 280 Parameters
302 281 ----------
303 282 func : callable
304 283 The function to be tested. Should accept a single argument.
305 284 pairs : iterable
306 285 A list of (input, expected_output) tuples.
307 286
308 287 Returns
309 288 -------
310 289 None. Raises an AssertionError if any output does not match the expected
311 290 value.
312 291 """
313 292 name = getattr(func, "func_name", getattr(func, "__name__", "<unknown>"))
314 293 for inp, expected in pairs:
315 294 out = func(inp)
316 295 assert out == expected, pair_fail_msg.format(name, inp, expected, out)
317 296
318 297
319 298 if py3compat.PY3:
320 299 MyStringIO = StringIO
321 300 else:
322 301 # In Python 2, stdout/stderr can have either bytes or unicode written to them,
323 302 # so we need a class that can handle both.
324 303 class MyStringIO(StringIO):
325 304 def write(self, s):
326 305 s = py3compat.cast_unicode(s, encoding=DEFAULT_ENCODING)
327 306 super(MyStringIO, self).write(s)
328 307
329 308 notprinted_msg = """Did not find {0!r} in printed output (on {1}):
330 309 {2!r}"""
331 310
332 311 class AssertPrints(object):
333 312 """Context manager for testing that code prints certain text.
334 313
335 314 Examples
336 315 --------
337 316 >>> with AssertPrints("abc", suppress=False):
338 317 ... print "abcd"
339 318 ... print "def"
340 319 ...
341 320 abcd
342 321 def
343 322 """
344 323 def __init__(self, s, channel='stdout', suppress=True):
345 324 self.s = s
346 325 self.channel = channel
347 326 self.suppress = suppress
348 327
349 328 def __enter__(self):
350 329 self.orig_stream = getattr(sys, self.channel)
351 330 self.buffer = MyStringIO()
352 331 self.tee = Tee(self.buffer, channel=self.channel)
353 332 setattr(sys, self.channel, self.buffer if self.suppress else self.tee)
354 333
355 334 def __exit__(self, etype, value, traceback):
356 335 self.tee.flush()
357 336 setattr(sys, self.channel, self.orig_stream)
358 337 printed = self.buffer.getvalue()
359 338 assert self.s in printed, notprinted_msg.format(self.s, self.channel, printed)
360 339 return False
361 340
362 341 class AssertNotPrints(AssertPrints):
363 342 """Context manager for checking that certain output *isn't* produced.
364 343
365 344 Counterpart of AssertPrints"""
366 345 def __exit__(self, etype, value, traceback):
367 346 self.tee.flush()
368 347 setattr(sys, self.channel, self.orig_stream)
369 348 printed = self.buffer.getvalue()
370 349 assert self.s not in printed, notprinted_msg.format(self.s, self.channel, printed)
371 350 return False
372 351
373 352 @contextmanager
374 353 def mute_warn():
375 354 from IPython.utils import warn
376 355 save_warn = warn.warn
377 356 warn.warn = lambda *a, **kw: None
378 357 try:
379 358 yield
380 359 finally:
381 360 warn.warn = save_warn
382 361
383 362 @contextmanager
384 363 def make_tempfile(name):
385 364 """ Create an empty, named, temporary file for the duration of the context.
386 365 """
387 366 f = open(name, 'w')
388 367 f.close()
389 368 try:
390 369 yield
391 370 finally:
392 371 os.unlink(name)
General Comments 0
You need to be logged in to leave comments. Login now