##// END OF EJS Templates
Cleanup some of the skip-if decorators....
Matthias Bussonnier -
Show More
@@ -1,510 +1,508 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
11 11 # Copyright (c) IPython Development Team.
12 12 # Distributed under the terms of the Modified BSD License.
13 13
14 14 from __future__ import absolute_import
15 15
16 16
17 17 import functools
18 18 import os
19 19 from os.path import join as pjoin
20 20 import random
21 21 import sys
22 import tempfile
23 22 import textwrap
24 23 import unittest
25 24
26 25 try:
27 26 from unittest.mock import patch
28 27 except ImportError:
29 28 from mock import patch
30 29
31 30 import nose.tools as nt
32 31 from nose import SkipTest
33 32
34 33 from IPython.testing import decorators as dec
35 34 from IPython.testing import tools as tt
36 35 from IPython.utils import py3compat
37 36 from IPython.utils.io import capture_output
38 37 from IPython.utils.tempdir import TemporaryDirectory
39 38 from IPython.core import debugger
40 39
41 40
42 41 def doctest_refbug():
43 42 """Very nasty problem with references held by multiple runs of a script.
44 43 See: https://github.com/ipython/ipython/issues/141
45 44
46 45 In [1]: _ip.clear_main_mod_cache()
47 46 # random
48 47
49 48 In [2]: %run refbug
50 49
51 50 In [3]: call_f()
52 51 lowercased: hello
53 52
54 53 In [4]: %run refbug
55 54
56 55 In [5]: call_f()
57 56 lowercased: hello
58 57 lowercased: hello
59 58 """
60 59
61 60
62 61 def doctest_run_builtins():
63 62 r"""Check that %run doesn't damage __builtins__.
64 63
65 64 In [1]: import tempfile
66 65
67 66 In [2]: bid1 = id(__builtins__)
68 67
69 68 In [3]: fname = tempfile.mkstemp('.py')[1]
70 69
71 70 In [3]: f = open(fname,'w')
72 71
73 72 In [4]: dummy= f.write('pass\n')
74 73
75 74 In [5]: f.flush()
76 75
77 76 In [6]: t1 = type(__builtins__)
78 77
79 78 In [7]: %run $fname
80 79
81 80 In [7]: f.close()
82 81
83 82 In [8]: bid2 = id(__builtins__)
84 83
85 84 In [9]: t2 = type(__builtins__)
86 85
87 86 In [10]: t1 == t2
88 87 Out[10]: True
89 88
90 89 In [10]: bid1 == bid2
91 90 Out[10]: True
92 91
93 92 In [12]: try:
94 93 ....: os.unlink(fname)
95 94 ....: except:
96 95 ....: pass
97 96 ....:
98 97 """
99 98
100 99
101 100 def doctest_run_option_parser():
102 101 r"""Test option parser in %run.
103 102
104 103 In [1]: %run print_argv.py
105 104 []
106 105
107 106 In [2]: %run print_argv.py print*.py
108 107 ['print_argv.py']
109 108
110 109 In [3]: %run -G print_argv.py print*.py
111 110 ['print*.py']
112 111
113 112 """
114 113
115 114
116 115 @dec.skip_win32
117 116 def doctest_run_option_parser_for_posix():
118 117 r"""Test option parser in %run (Linux/OSX specific).
119 118
120 119 You need double quote to escape glob in POSIX systems:
121 120
122 121 In [1]: %run print_argv.py print\\*.py
123 122 ['print*.py']
124 123
125 124 You can't use quote to escape glob in POSIX systems:
126 125
127 126 In [2]: %run print_argv.py 'print*.py'
128 127 ['print_argv.py']
129 128
130 129 """
131 130
132 131
133 132 @dec.skip_if_not_win32
134 133 def doctest_run_option_parser_for_windows():
135 134 r"""Test option parser in %run (Windows specific).
136 135
137 136 In Windows, you can't escape ``*` `by backslash:
138 137
139 138 In [1]: %run print_argv.py print\\*.py
140 139 ['print\\*.py']
141 140
142 141 You can use quote to escape glob:
143 142
144 143 In [2]: %run print_argv.py 'print*.py'
145 144 ['print*.py']
146 145
147 146 """
148 147
149 148
150 149 @py3compat.doctest_refactor_print
151 150 def doctest_reset_del():
152 151 """Test that resetting doesn't cause errors in __del__ methods.
153 152
154 153 In [2]: class A(object):
155 154 ...: def __del__(self):
156 155 ...: print str("Hi")
157 156 ...:
158 157
159 158 In [3]: a = A()
160 159
161 160 In [4]: get_ipython().reset()
162 161 Hi
163 162
164 163 In [5]: 1+1
165 164 Out[5]: 2
166 165 """
167 166
168 167 # For some tests, it will be handy to organize them in a class with a common
169 168 # setup that makes a temp file
170 169
171 170 class TestMagicRunPass(tt.TempFileMixin):
172 171
173 172 def setup(self):
174 173 """Make a valid python temp file."""
175 174 self.mktmp('pass\n')
176 175
177 176 def run_tmpfile(self):
178 177 _ip = get_ipython()
179 178 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
180 179 # See below and ticket https://bugs.launchpad.net/bugs/366353
181 180 _ip.magic('run %s' % self.fname)
182 181
183 182 def run_tmpfile_p(self):
184 183 _ip = get_ipython()
185 184 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
186 185 # See below and ticket https://bugs.launchpad.net/bugs/366353
187 186 _ip.magic('run -p %s' % self.fname)
188 187
189 188 def test_builtins_id(self):
190 189 """Check that %run doesn't damage __builtins__ """
191 190 _ip = get_ipython()
192 191 # Test that the id of __builtins__ is not modified by %run
193 192 bid1 = id(_ip.user_ns['__builtins__'])
194 193 self.run_tmpfile()
195 194 bid2 = id(_ip.user_ns['__builtins__'])
196 195 nt.assert_equal(bid1, bid2)
197 196
198 197 def test_builtins_type(self):
199 198 """Check that the type of __builtins__ doesn't change with %run.
200 199
201 200 However, the above could pass if __builtins__ was already modified to
202 201 be a dict (it should be a module) by a previous use of %run. So we
203 202 also check explicitly that it really is a module:
204 203 """
205 204 _ip = get_ipython()
206 205 self.run_tmpfile()
207 206 nt.assert_equal(type(_ip.user_ns['__builtins__']),type(sys))
208 207
209 208 def test_run_profile( self ):
210 209 """Test that the option -p, which invokes the profiler, do not
211 210 crash by invoking execfile"""
212 _ip = get_ipython()
211 get_ipython()
213 212 self.run_tmpfile_p()
214 213
215 214
216 215 class TestMagicRunSimple(tt.TempFileMixin):
217 216
218 217 def test_simpledef(self):
219 218 """Test that simple class definitions work."""
220 219 src = ("class foo: pass\n"
221 220 "def f(): return foo()")
222 221 self.mktmp(src)
223 222 _ip.magic('run %s' % self.fname)
224 223 _ip.run_cell('t = isinstance(f(), foo)')
225 224 nt.assert_true(_ip.user_ns['t'])
226 225
227 226 def test_obj_del(self):
228 227 """Test that object's __del__ methods are called on exit."""
229 228 if sys.platform == 'win32':
230 229 try:
231 230 import win32api
232 231 except ImportError:
233 232 raise SkipTest("Test requires pywin32")
234 233 src = ("class A(object):\n"
235 234 " def __del__(self):\n"
236 235 " print 'object A deleted'\n"
237 236 "a = A()\n")
238 237 self.mktmp(py3compat.doctest_refactor_print(src))
239 238 if dec.module_not_available('sqlite3'):
240 239 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
241 240 else:
242 241 err = None
243 242 tt.ipexec_validate(self.fname, 'object A deleted', err)
244 243
245 244 def test_aggressive_namespace_cleanup(self):
246 245 """Test that namespace cleanup is not too aggressive GH-238
247 246
248 247 Returning from another run magic deletes the namespace"""
249 248 # see ticket https://github.com/ipython/ipython/issues/238
250 249
251 250 with tt.TempFileMixin() as empty:
252 251 empty.mktmp('')
253 252 # On Windows, the filename will have \users in it, so we need to use the
254 253 # repr so that the \u becomes \\u.
255 254 src = ("ip = get_ipython()\n"
256 255 "for i in range(5):\n"
257 256 " try:\n"
258 257 " ip.magic(%r)\n"
259 258 " except NameError as e:\n"
260 259 " print(i)\n"
261 260 " break\n" % ('run ' + empty.fname))
262 261 self.mktmp(src)
263 262 _ip.magic('run %s' % self.fname)
264 263 _ip.run_cell('ip == get_ipython()')
265 264 nt.assert_equal(_ip.user_ns['i'], 4)
266 265
267 266 def test_run_second(self):
268 267 """Test that running a second file doesn't clobber the first, gh-3547
269 268 """
270 269 self.mktmp("avar = 1\n"
271 270 "def afunc():\n"
272 271 " return avar\n")
273 272
274 273 with tt.TempFileMixin() as empty:
275 274 empty.mktmp("")
276 275
277 276 _ip.magic('run %s' % self.fname)
278 277 _ip.magic('run %s' % empty.fname)
279 278 nt.assert_equal(_ip.user_ns['afunc'](), 1)
280 279
281 280 @dec.skip_win32
282 281 def test_tclass(self):
283 282 mydir = os.path.dirname(__file__)
284 283 tc = os.path.join(mydir, 'tclass')
285 284 src = ("%%run '%s' C-first\n"
286 285 "%%run '%s' C-second\n"
287 286 "%%run '%s' C-third\n") % (tc, tc, tc)
288 287 self.mktmp(src, '.ipy')
289 288 out = """\
290 289 ARGV 1-: ['C-first']
291 290 ARGV 1-: ['C-second']
292 291 tclass.py: deleting object: C-first
293 292 ARGV 1-: ['C-third']
294 293 tclass.py: deleting object: C-second
295 294 tclass.py: deleting object: C-third
296 295 """
297 296 if dec.module_not_available('sqlite3'):
298 297 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
299 298 else:
300 299 err = None
301 300 tt.ipexec_validate(self.fname, out, err)
302 301
303 302 def test_run_i_after_reset(self):
304 303 """Check that %run -i still works after %reset (gh-693)"""
305 304 src = "yy = zz\n"
306 305 self.mktmp(src)
307 306 _ip.run_cell("zz = 23")
308 307 _ip.magic('run -i %s' % self.fname)
309 308 nt.assert_equal(_ip.user_ns['yy'], 23)
310 309 _ip.magic('reset -f')
311 310 _ip.run_cell("zz = 23")
312 311 _ip.magic('run -i %s' % self.fname)
313 312 nt.assert_equal(_ip.user_ns['yy'], 23)
314 313
315 314 def test_unicode(self):
316 315 """Check that files in odd encodings are accepted."""
317 316 mydir = os.path.dirname(__file__)
318 317 na = os.path.join(mydir, 'nonascii.py')
319 318 _ip.magic('run "%s"' % na)
320 319 nt.assert_equal(_ip.user_ns['u'], u'Ўт№Ф')
321 320
322 321 def test_run_py_file_attribute(self):
323 322 """Test handling of `__file__` attribute in `%run <file>.py`."""
324 323 src = "t = __file__\n"
325 324 self.mktmp(src)
326 325 _missing = object()
327 326 file1 = _ip.user_ns.get('__file__', _missing)
328 327 _ip.magic('run %s' % self.fname)
329 328 file2 = _ip.user_ns.get('__file__', _missing)
330 329
331 330 # Check that __file__ was equal to the filename in the script's
332 331 # namespace.
333 332 nt.assert_equal(_ip.user_ns['t'], self.fname)
334 333
335 334 # Check that __file__ was not leaked back into user_ns.
336 335 nt.assert_equal(file1, file2)
337 336
338 337 def test_run_ipy_file_attribute(self):
339 338 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
340 339 src = "t = __file__\n"
341 340 self.mktmp(src, ext='.ipy')
342 341 _missing = object()
343 342 file1 = _ip.user_ns.get('__file__', _missing)
344 343 _ip.magic('run %s' % self.fname)
345 344 file2 = _ip.user_ns.get('__file__', _missing)
346 345
347 346 # Check that __file__ was equal to the filename in the script's
348 347 # namespace.
349 348 nt.assert_equal(_ip.user_ns['t'], self.fname)
350 349
351 350 # Check that __file__ was not leaked back into user_ns.
352 351 nt.assert_equal(file1, file2)
353 352
354 353 def test_run_formatting(self):
355 354 """ Test that %run -t -N<N> does not raise a TypeError for N > 1."""
356 355 src = "pass"
357 356 self.mktmp(src)
358 357 _ip.magic('run -t -N 1 %s' % self.fname)
359 358 _ip.magic('run -t -N 10 %s' % self.fname)
360 359
361 360 def test_ignore_sys_exit(self):
362 361 """Test the -e option to ignore sys.exit()"""
363 362 src = "import sys; sys.exit(1)"
364 363 self.mktmp(src)
365 364 with tt.AssertPrints('SystemExit'):
366 365 _ip.magic('run %s' % self.fname)
367 366
368 367 with tt.AssertNotPrints('SystemExit'):
369 368 _ip.magic('run -e %s' % self.fname)
370 369
371 @dec.skip_without('nbformat') # Requires jsonschema
372 370 def test_run_nb(self):
373 371 """Test %run notebook.ipynb"""
374 372 from nbformat import v4, writes
375 373 nb = v4.new_notebook(
376 374 cells=[
377 375 v4.new_markdown_cell("The Ultimate Question of Everything"),
378 376 v4.new_code_cell("answer=42")
379 377 ]
380 378 )
381 379 src = writes(nb, version=4)
382 380 self.mktmp(src, ext='.ipynb')
383 381
384 382 _ip.magic("run %s" % self.fname)
385 383
386 384 nt.assert_equal(_ip.user_ns['answer'], 42)
387 385
388 386
389 387
390 388 class TestMagicRunWithPackage(unittest.TestCase):
391 389
392 390 def writefile(self, name, content):
393 391 path = os.path.join(self.tempdir.name, name)
394 392 d = os.path.dirname(path)
395 393 if not os.path.isdir(d):
396 394 os.makedirs(d)
397 395 with open(path, 'w') as f:
398 396 f.write(textwrap.dedent(content))
399 397
400 398 def setUp(self):
401 399 self.package = package = 'tmp{0}'.format(repr(random.random())[2:])
402 400 """Temporary valid python package name."""
403 401
404 402 self.value = int(random.random() * 10000)
405 403
406 404 self.tempdir = TemporaryDirectory()
407 405 self.__orig_cwd = py3compat.getcwd()
408 406 sys.path.insert(0, self.tempdir.name)
409 407
410 408 self.writefile(os.path.join(package, '__init__.py'), '')
411 409 self.writefile(os.path.join(package, 'sub.py'), """
412 410 x = {0!r}
413 411 """.format(self.value))
414 412 self.writefile(os.path.join(package, 'relative.py'), """
415 413 from .sub import x
416 414 """)
417 415 self.writefile(os.path.join(package, 'absolute.py'), """
418 416 from {0}.sub import x
419 417 """.format(package))
420 418
421 419 def tearDown(self):
422 420 os.chdir(self.__orig_cwd)
423 421 sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
424 422 self.tempdir.cleanup()
425 423
426 424 def check_run_submodule(self, submodule, opts=''):
427 425 _ip.user_ns.pop('x', None)
428 426 _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
429 427 self.assertEqual(_ip.user_ns['x'], self.value,
430 428 'Variable `x` is not loaded from module `{0}`.'
431 429 .format(submodule))
432 430
433 431 def test_run_submodule_with_absolute_import(self):
434 432 self.check_run_submodule('absolute')
435 433
436 434 def test_run_submodule_with_relative_import(self):
437 435 """Run submodule that has a relative import statement (#2727)."""
438 436 self.check_run_submodule('relative')
439 437
440 438 def test_prun_submodule_with_absolute_import(self):
441 439 self.check_run_submodule('absolute', '-p')
442 440
443 441 def test_prun_submodule_with_relative_import(self):
444 442 self.check_run_submodule('relative', '-p')
445 443
446 444 def with_fake_debugger(func):
447 445 @functools.wraps(func)
448 446 def wrapper(*args, **kwds):
449 447 with patch.object(debugger.Pdb, 'run', staticmethod(eval)):
450 448 return func(*args, **kwds)
451 449 return wrapper
452 450
453 451 @with_fake_debugger
454 452 def test_debug_run_submodule_with_absolute_import(self):
455 453 self.check_run_submodule('absolute', '-d')
456 454
457 455 @with_fake_debugger
458 456 def test_debug_run_submodule_with_relative_import(self):
459 457 self.check_run_submodule('relative', '-d')
460 458
461 459 def test_run__name__():
462 460 with TemporaryDirectory() as td:
463 461 path = pjoin(td, 'foo.py')
464 462 with open(path, 'w') as f:
465 463 f.write("q = __name__")
466 464
467 465 _ip.user_ns.pop('q', None)
468 466 _ip.magic('run {}'.format(path))
469 467 nt.assert_equal(_ip.user_ns.pop('q'), '__main__')
470 468
471 469 _ip.magic('run -n {}'.format(path))
472 470 nt.assert_equal(_ip.user_ns.pop('q'), 'foo')
473 471
474 472 def test_run_tb():
475 473 """Test traceback offset in %run"""
476 474 with TemporaryDirectory() as td:
477 475 path = pjoin(td, 'foo.py')
478 476 with open(path, 'w') as f:
479 477 f.write('\n'.join([
480 478 "def foo():",
481 479 " return bar()",
482 480 "def bar():",
483 481 " raise RuntimeError('hello!')",
484 482 "foo()",
485 483 ]))
486 484 with capture_output() as io:
487 485 _ip.magic('run {}'.format(path))
488 486 out = io.stdout
489 487 nt.assert_not_in("execfile", out)
490 488 nt.assert_in("RuntimeError", out)
491 489 nt.assert_equal(out.count("---->"), 3)
492 490
493 491 @dec.knownfailureif(sys.platform == 'win32', "writes to io.stdout aren't captured on Windows")
494 492 def test_script_tb():
495 493 """Test traceback offset in `ipython script.py`"""
496 494 with TemporaryDirectory() as td:
497 495 path = pjoin(td, 'foo.py')
498 496 with open(path, 'w') as f:
499 497 f.write('\n'.join([
500 498 "def foo():",
501 499 " return bar()",
502 500 "def bar():",
503 501 " raise RuntimeError('hello!')",
504 502 "foo()",
505 503 ]))
506 504 out, err = tt.ipexec(path)
507 505 nt.assert_not_in("execfile", out)
508 506 nt.assert_in("RuntimeError", out)
509 507 nt.assert_equal(out.count("---->"), 3)
510 508
@@ -1,68 +1,56 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for shellapp module.
3 3
4 4 Authors
5 5 -------
6 6 * Bradley Froehle
7 7 """
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2012 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18 import unittest
19 19
20 20 from IPython.testing import decorators as dec
21 21 from IPython.testing import tools as tt
22 from IPython.utils.py3compat import PY3
23 22
24 23 sqlite_err_maybe = dec.module_not_available('sqlite3')
25 24 SQLITE_NOT_AVAILABLE_ERROR = ('WARNING: IPython History requires SQLite,'
26 25 ' your history will not be saved\n')
27 26
28 27 class TestFileToRun(unittest.TestCase, tt.TempFileMixin):
29 28 """Test the behavior of the file_to_run parameter."""
30 29
31 30 def test_py_script_file_attribute(self):
32 31 """Test that `__file__` is set when running `ipython file.py`"""
33 32 src = "print(__file__)\n"
34 33 self.mktmp(src)
35 34
36 35 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
37 36 tt.ipexec_validate(self.fname, self.fname, err)
38 37
39 38 def test_ipy_script_file_attribute(self):
40 39 """Test that `__file__` is set when running `ipython file.ipy`"""
41 40 src = "print(__file__)\n"
42 41 self.mktmp(src, ext='.ipy')
43 42
44 43 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
45 44 tt.ipexec_validate(self.fname, self.fname, err)
46 45
47 46 # The commands option to ipexec_validate doesn't work on Windows, and it
48 47 # doesn't seem worth fixing
49 48 @dec.skip_win32
50 49 def test_py_script_file_attribute_interactively(self):
51 50 """Test that `__file__` is not set after `ipython -i file.py`"""
52 51 src = "True\n"
53 52 self.mktmp(src)
54 53
55 54 out, err = tt.ipexec(self.fname, options=['-i'],
56 55 commands=['"__file__" in globals()', 'exit()'])
57 56 self.assertIn("False", out)
58
59 @dec.skip_win32
60 @dec.skipif(PY3)
61 def test_py_script_file_compiler_directive(self):
62 """Test `__future__` compiler directives with `ipython -i file.py`"""
63 src = "from __future__ import division\n"
64 self.mktmp(src)
65
66 out, err = tt.ipexec(self.fname, options=['-i'],
67 commands=['type(1/2)', 'exit()'])
68 self.assertIn('float', out)
@@ -1,536 +1,487 b''
1 1 # coding: utf-8
2 2 """Tests for IPython.lib.pretty."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7 from __future__ import print_function
8 8
9 9 from collections import Counter, defaultdict, deque, OrderedDict
10 import types, string, ctypes
10 import types, string
11 11
12 12 import nose.tools as nt
13 13
14 14 from IPython.lib import pretty
15 from IPython.testing.decorators import (skip_without, py2_only, py3_only,
16 cpython2_only)
15 from IPython.testing.decorators import (skip_without, py2_only, py3_only)
16
17 17 from IPython.utils.py3compat import PY3, unicode_to_str
18 18
19 19 if PY3:
20 20 from io import StringIO
21 21 else:
22 22 from StringIO import StringIO
23 23
24 24
25 25 class MyList(object):
26 26 def __init__(self, content):
27 27 self.content = content
28 28 def _repr_pretty_(self, p, cycle):
29 29 if cycle:
30 30 p.text("MyList(...)")
31 31 else:
32 32 with p.group(3, "MyList(", ")"):
33 33 for (i, child) in enumerate(self.content):
34 34 if i:
35 35 p.text(",")
36 36 p.breakable()
37 37 else:
38 38 p.breakable("")
39 39 p.pretty(child)
40 40
41 41
42 42 class MyDict(dict):
43 43 def _repr_pretty_(self, p, cycle):
44 44 p.text("MyDict(...)")
45 45
46 46 class MyObj(object):
47 47 def somemethod(self):
48 48 pass
49 49
50 50
51 51 class Dummy1(object):
52 52 def _repr_pretty_(self, p, cycle):
53 53 p.text("Dummy1(...)")
54 54
55 55 class Dummy2(Dummy1):
56 56 _repr_pretty_ = None
57 57
58 58 class NoModule(object):
59 59 pass
60 60
61 61 NoModule.__module__ = None
62 62
63 63 class Breaking(object):
64 64 def _repr_pretty_(self, p, cycle):
65 65 with p.group(4,"TG: ",":"):
66 66 p.text("Breaking(")
67 67 p.break_()
68 68 p.text(")")
69 69
70 70 class BreakingRepr(object):
71 71 def __repr__(self):
72 72 return "Breaking(\n)"
73 73
74 74 class BreakingReprParent(object):
75 75 def _repr_pretty_(self, p, cycle):
76 76 with p.group(4,"TG: ",":"):
77 77 p.pretty(BreakingRepr())
78 78
79 79 class BadRepr(object):
80 80
81 81 def __repr__(self):
82 82 return 1/0
83 83
84 84
85 85 def test_indentation():
86 86 """Test correct indentation in groups"""
87 87 count = 40
88 88 gotoutput = pretty.pretty(MyList(range(count)))
89 89 expectedoutput = "MyList(\n" + ",\n".join(" %d" % i for i in range(count)) + ")"
90 90
91 91 nt.assert_equal(gotoutput, expectedoutput)
92 92
93 93
94 94 def test_dispatch():
95 95 """
96 96 Test correct dispatching: The _repr_pretty_ method for MyDict
97 97 must be found before the registered printer for dict.
98 98 """
99 99 gotoutput = pretty.pretty(MyDict())
100 100 expectedoutput = "MyDict(...)"
101 101
102 102 nt.assert_equal(gotoutput, expectedoutput)
103 103
104 104
105 105 def test_callability_checking():
106 106 """
107 107 Test that the _repr_pretty_ method is tested for callability and skipped if
108 108 not.
109 109 """
110 110 gotoutput = pretty.pretty(Dummy2())
111 111 expectedoutput = "Dummy1(...)"
112 112
113 113 nt.assert_equal(gotoutput, expectedoutput)
114 114
115 115
116 116 def test_sets():
117 117 """
118 118 Test that set and frozenset use Python 3 formatting.
119 119 """
120 120 objects = [set(), frozenset(), set([1]), frozenset([1]), set([1, 2]),
121 121 frozenset([1, 2]), set([-1, -2, -3])]
122 122 expected = ['set()', 'frozenset()', '{1}', 'frozenset({1})', '{1, 2}',
123 123 'frozenset({1, 2})', '{-3, -2, -1}']
124 124 for obj, expected_output in zip(objects, expected):
125 125 got_output = pretty.pretty(obj)
126 126 yield nt.assert_equal, got_output, expected_output
127 127
128 128
129 129 @skip_without('xxlimited')
130 130 def test_pprint_heap_allocated_type():
131 131 """
132 132 Test that pprint works for heap allocated types.
133 133 """
134 134 import xxlimited
135 135 output = pretty.pretty(xxlimited.Null)
136 136 nt.assert_equal(output, 'xxlimited.Null')
137 137
138 138 def test_pprint_nomod():
139 139 """
140 140 Test that pprint works for classes with no __module__.
141 141 """
142 142 output = pretty.pretty(NoModule)
143 143 nt.assert_equal(output, 'NoModule')
144 144
145 145 def test_pprint_break():
146 146 """
147 147 Test that p.break_ produces expected output
148 148 """
149 149 output = pretty.pretty(Breaking())
150 150 expected = "TG: Breaking(\n ):"
151 151 nt.assert_equal(output, expected)
152 152
153 153 def test_pprint_break_repr():
154 154 """
155 155 Test that p.break_ is used in repr
156 156 """
157 157 output = pretty.pretty(BreakingReprParent())
158 158 expected = "TG: Breaking(\n ):"
159 159 nt.assert_equal(output, expected)
160 160
161 161 def test_bad_repr():
162 162 """Don't catch bad repr errors"""
163 163 with nt.assert_raises(ZeroDivisionError):
164 output = pretty.pretty(BadRepr())
164 pretty.pretty(BadRepr())
165 165
166 166 class BadException(Exception):
167 167 def __str__(self):
168 168 return -1
169 169
170 170 class ReallyBadRepr(object):
171 171 __module__ = 1
172 172 @property
173 173 def __class__(self):
174 174 raise ValueError("I am horrible")
175 175
176 176 def __repr__(self):
177 177 raise BadException()
178 178
179 179 def test_really_bad_repr():
180 180 with nt.assert_raises(BadException):
181 output = pretty.pretty(ReallyBadRepr())
181 pretty.pretty(ReallyBadRepr())
182 182
183 183
184 184 class SA(object):
185 185 pass
186 186
187 187 class SB(SA):
188 188 pass
189 189
190 190 def test_super_repr():
191 191 # "<super: module_name.SA, None>"
192 192 output = pretty.pretty(super(SA))
193 193 nt.assert_regexp_matches(output, r"<super: \S+.SA, None>")
194 194
195 195 # "<super: module_name.SA, <module_name.SB at 0x...>>"
196 196 sb = SB()
197 197 output = pretty.pretty(super(SA, sb))
198 198 nt.assert_regexp_matches(output, r"<super: \S+.SA,\s+<\S+.SB at 0x\S+>>")
199 199
200 200
201 201 def test_long_list():
202 202 lis = list(range(10000))
203 203 p = pretty.pretty(lis)
204 204 last2 = p.rsplit('\n', 2)[-2:]
205 205 nt.assert_equal(last2, [' 999,', ' ...]'])
206 206
207 207 def test_long_set():
208 208 s = set(range(10000))
209 209 p = pretty.pretty(s)
210 210 last2 = p.rsplit('\n', 2)[-2:]
211 211 nt.assert_equal(last2, [' 999,', ' ...}'])
212 212
213 213 def test_long_tuple():
214 214 tup = tuple(range(10000))
215 215 p = pretty.pretty(tup)
216 216 last2 = p.rsplit('\n', 2)[-2:]
217 217 nt.assert_equal(last2, [' 999,', ' ...)'])
218 218
219 219 def test_long_dict():
220 220 d = { n:n for n in range(10000) }
221 221 p = pretty.pretty(d)
222 222 last2 = p.rsplit('\n', 2)[-2:]
223 223 nt.assert_equal(last2, [' 999: 999,', ' ...}'])
224 224
225 225 def test_unbound_method():
226 226 output = pretty.pretty(MyObj.somemethod)
227 227 nt.assert_in('MyObj.somemethod', output)
228 228
229 229
230 230 class MetaClass(type):
231 231 def __new__(cls, name):
232 232 return type.__new__(cls, name, (object,), {'name': name})
233 233
234 234 def __repr__(self):
235 235 return "[CUSTOM REPR FOR CLASS %s]" % self.name
236 236
237 237
238 238 ClassWithMeta = MetaClass('ClassWithMeta')
239 239
240 240
241 241 def test_metaclass_repr():
242 242 output = pretty.pretty(ClassWithMeta)
243 243 nt.assert_equal(output, "[CUSTOM REPR FOR CLASS ClassWithMeta]")
244 244
245 245
246 246 def test_unicode_repr():
247 247 u = u"üniçodé"
248 248 ustr = unicode_to_str(u)
249 249
250 250 class C(object):
251 251 def __repr__(self):
252 252 return ustr
253 253
254 254 c = C()
255 255 p = pretty.pretty(c)
256 256 nt.assert_equal(p, u)
257 257 p = pretty.pretty([c])
258 258 nt.assert_equal(p, u'[%s]' % u)
259 259
260 260
261 261 def test_basic_class():
262 262 def type_pprint_wrapper(obj, p, cycle):
263 263 if obj is MyObj:
264 264 type_pprint_wrapper.called = True
265 265 return pretty._type_pprint(obj, p, cycle)
266 266 type_pprint_wrapper.called = False
267 267
268 268 stream = StringIO()
269 269 printer = pretty.RepresentationPrinter(stream)
270 270 printer.type_pprinters[type] = type_pprint_wrapper
271 271 printer.pretty(MyObj)
272 272 printer.flush()
273 273 output = stream.getvalue()
274 274
275 275 nt.assert_equal(output, '%s.MyObj' % __name__)
276 276 nt.assert_true(type_pprint_wrapper.called)
277 277
278 278
279 279 # This is only run on Python 2 because in Python 3 the language prevents you
280 280 # from setting a non-unicode value for __qualname__ on a metaclass, and it
281 281 # doesn't respect the descriptor protocol if you subclass unicode and implement
282 282 # __get__.
283 283 @py2_only
284 284 def test_fallback_to__name__on_type():
285 285 # Test that we correctly repr types that have non-string values for
286 286 # __qualname__ by falling back to __name__
287 287
288 288 class Type(object):
289 289 __qualname__ = 5
290 290
291 291 # Test repring of the type.
292 292 stream = StringIO()
293 293 printer = pretty.RepresentationPrinter(stream)
294 294
295 295 printer.pretty(Type)
296 296 printer.flush()
297 297 output = stream.getvalue()
298 298
299 299 # If __qualname__ is malformed, we should fall back to __name__.
300 300 expected = '.'.join([__name__, Type.__name__])
301 301 nt.assert_equal(output, expected)
302 302
303 303 # Clear stream buffer.
304 304 stream.buf = ''
305 305
306 306 # Test repring of an instance of the type.
307 307 instance = Type()
308 308 printer.pretty(instance)
309 309 printer.flush()
310 310 output = stream.getvalue()
311 311
312 312 # Should look like:
313 313 # <IPython.lib.tests.test_pretty.Type at 0x7f7658ae07d0>
314 314 prefix = '<' + '.'.join([__name__, Type.__name__]) + ' at 0x'
315 315 nt.assert_true(output.startswith(prefix))
316 316
317 317
318 318 @py2_only
319 319 def test_fail_gracefully_on_bogus__qualname__and__name__():
320 320 # Test that we correctly repr types that have non-string values for both
321 321 # __qualname__ and __name__
322 322
323 323 class Meta(type):
324 324 __name__ = 5
325 325
326 326 class Type(object):
327 327 __metaclass__ = Meta
328 328 __qualname__ = 5
329 329
330 330 stream = StringIO()
331 331 printer = pretty.RepresentationPrinter(stream)
332 332
333 333 printer.pretty(Type)
334 334 printer.flush()
335 335 output = stream.getvalue()
336 336
337 337 # If we can't find __name__ or __qualname__ just use a sentinel string.
338 338 expected = '.'.join([__name__, '<unknown type>'])
339 339 nt.assert_equal(output, expected)
340 340
341 341 # Clear stream buffer.
342 342 stream.buf = ''
343 343
344 344 # Test repring of an instance of the type.
345 345 instance = Type()
346 346 printer.pretty(instance)
347 347 printer.flush()
348 348 output = stream.getvalue()
349 349
350 350 # Should look like:
351 351 # <IPython.lib.tests.test_pretty.<unknown type> at 0x7f7658ae07d0>
352 352 prefix = '<' + '.'.join([__name__, '<unknown type>']) + ' at 0x'
353 353 nt.assert_true(output.startswith(prefix))
354 354
355 355
356 356 def test_collections_defaultdict():
357 357 # Create defaultdicts with cycles
358 358 a = defaultdict()
359 359 a.default_factory = a
360 360 b = defaultdict(list)
361 361 b['key'] = b
362 362
363 363 # Dictionary order cannot be relied on, test against single keys.
364 364 cases = [
365 365 (defaultdict(list), 'defaultdict(list, {})'),
366 366 (defaultdict(list, {'key': '-' * 50}),
367 367 "defaultdict(list,\n"
368 368 " {'key': '--------------------------------------------------'})"),
369 369 (a, 'defaultdict(defaultdict(...), {})'),
370 370 (b, "defaultdict(list, {'key': defaultdict(...)})"),
371 371 ]
372 372 for obj, expected in cases:
373 373 nt.assert_equal(pretty.pretty(obj), expected)
374 374
375 375
376 376 def test_collections_ordereddict():
377 377 # Create OrderedDict with cycle
378 378 a = OrderedDict()
379 379 a['key'] = a
380 380
381 381 cases = [
382 382 (OrderedDict(), 'OrderedDict()'),
383 383 (OrderedDict((i, i) for i in range(1000, 1010)),
384 384 'OrderedDict([(1000, 1000),\n'
385 385 ' (1001, 1001),\n'
386 386 ' (1002, 1002),\n'
387 387 ' (1003, 1003),\n'
388 388 ' (1004, 1004),\n'
389 389 ' (1005, 1005),\n'
390 390 ' (1006, 1006),\n'
391 391 ' (1007, 1007),\n'
392 392 ' (1008, 1008),\n'
393 393 ' (1009, 1009)])'),
394 394 (a, "OrderedDict([('key', OrderedDict(...))])"),
395 395 ]
396 396 for obj, expected in cases:
397 397 nt.assert_equal(pretty.pretty(obj), expected)
398 398
399 399
400 400 def test_collections_deque():
401 401 # Create deque with cycle
402 402 a = deque()
403 403 a.append(a)
404 404
405 405 cases = [
406 406 (deque(), 'deque([])'),
407 407 (deque(i for i in range(1000, 1020)),
408 408 'deque([1000,\n'
409 409 ' 1001,\n'
410 410 ' 1002,\n'
411 411 ' 1003,\n'
412 412 ' 1004,\n'
413 413 ' 1005,\n'
414 414 ' 1006,\n'
415 415 ' 1007,\n'
416 416 ' 1008,\n'
417 417 ' 1009,\n'
418 418 ' 1010,\n'
419 419 ' 1011,\n'
420 420 ' 1012,\n'
421 421 ' 1013,\n'
422 422 ' 1014,\n'
423 423 ' 1015,\n'
424 424 ' 1016,\n'
425 425 ' 1017,\n'
426 426 ' 1018,\n'
427 427 ' 1019])'),
428 428 (a, 'deque([deque(...)])'),
429 429 ]
430 430 for obj, expected in cases:
431 431 nt.assert_equal(pretty.pretty(obj), expected)
432 432
433 433 def test_collections_counter():
434 434 class MyCounter(Counter):
435 435 pass
436 436 cases = [
437 437 (Counter(), 'Counter()'),
438 438 (Counter(a=1), "Counter({'a': 1})"),
439 439 (MyCounter(a=1), "MyCounter({'a': 1})"),
440 440 ]
441 441 for obj, expected in cases:
442 442 nt.assert_equal(pretty.pretty(obj), expected)
443 443
444 444 @py3_only
445 445 def test_mappingproxy():
446 446 MP = types.MappingProxyType
447 447 underlying_dict = {}
448 448 mp_recursive = MP(underlying_dict)
449 449 underlying_dict[2] = mp_recursive
450 450 underlying_dict[3] = underlying_dict
451 451
452 452 cases = [
453 453 (MP({}), "mappingproxy({})"),
454 454 (MP({None: MP({})}), "mappingproxy({None: mappingproxy({})})"),
455 455 (MP({k: k.upper() for k in string.ascii_lowercase}),
456 456 "mappingproxy({'a': 'A',\n"
457 457 " 'b': 'B',\n"
458 458 " 'c': 'C',\n"
459 459 " 'd': 'D',\n"
460 460 " 'e': 'E',\n"
461 461 " 'f': 'F',\n"
462 462 " 'g': 'G',\n"
463 463 " 'h': 'H',\n"
464 464 " 'i': 'I',\n"
465 465 " 'j': 'J',\n"
466 466 " 'k': 'K',\n"
467 467 " 'l': 'L',\n"
468 468 " 'm': 'M',\n"
469 469 " 'n': 'N',\n"
470 470 " 'o': 'O',\n"
471 471 " 'p': 'P',\n"
472 472 " 'q': 'Q',\n"
473 473 " 'r': 'R',\n"
474 474 " 's': 'S',\n"
475 475 " 't': 'T',\n"
476 476 " 'u': 'U',\n"
477 477 " 'v': 'V',\n"
478 478 " 'w': 'W',\n"
479 479 " 'x': 'X',\n"
480 480 " 'y': 'Y',\n"
481 481 " 'z': 'Z'})"),
482 482 (mp_recursive, "mappingproxy({2: {...}, 3: {2: {...}, 3: {...}}})"),
483 483 (underlying_dict,
484 484 "{2: mappingproxy({2: {...}, 3: {...}}), 3: {...}}"),
485 485 ]
486 486 for obj, expected in cases:
487 487 nt.assert_equal(pretty.pretty(obj), expected)
488
489 @cpython2_only # In PyPy, types.DictProxyType is dict
490 def test_dictproxy():
491 # This is the dictproxy constructor itself from the Python API,
492 DP = ctypes.pythonapi.PyDictProxy_New
493 DP.argtypes, DP.restype = (ctypes.py_object,), ctypes.py_object
494
495 underlying_dict = {}
496 mp_recursive = DP(underlying_dict)
497 underlying_dict[0] = mp_recursive
498 underlying_dict[-3] = underlying_dict
499
500 cases = [
501 (DP({}), "dict_proxy({})"),
502 (DP({None: DP({})}), "dict_proxy({None: dict_proxy({})})"),
503 (DP({k: k.lower() for k in string.ascii_uppercase}),
504 "dict_proxy({'A': 'a',\n"
505 " 'B': 'b',\n"
506 " 'C': 'c',\n"
507 " 'D': 'd',\n"
508 " 'E': 'e',\n"
509 " 'F': 'f',\n"
510 " 'G': 'g',\n"
511 " 'H': 'h',\n"
512 " 'I': 'i',\n"
513 " 'J': 'j',\n"
514 " 'K': 'k',\n"
515 " 'L': 'l',\n"
516 " 'M': 'm',\n"
517 " 'N': 'n',\n"
518 " 'O': 'o',\n"
519 " 'P': 'p',\n"
520 " 'Q': 'q',\n"
521 " 'R': 'r',\n"
522 " 'S': 's',\n"
523 " 'T': 't',\n"
524 " 'U': 'u',\n"
525 " 'V': 'v',\n"
526 " 'W': 'w',\n"
527 " 'X': 'x',\n"
528 " 'Y': 'y',\n"
529 " 'Z': 'z'})"),
530 (mp_recursive, "dict_proxy({-3: {-3: {...}, 0: {...}}, 0: {...}})"),
531 ]
532 for obj, expected in cases:
533 nt.assert_is_instance(obj, types.DictProxyType) # Meta-test
534 nt.assert_equal(pretty.pretty(obj), expected)
535 nt.assert_equal(pretty.pretty(underlying_dict),
536 "{-3: {...}, 0: dict_proxy({-3: {...}, 0: {...}})}")
@@ -1,380 +1,379 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Decorators for labeling test objects.
3 3
4 4 Decorators that merely return a modified version of the original function
5 5 object are straightforward. Decorators that return a new function object need
6 6 to use nose.tools.make_decorator(original_function)(decorator) in returning the
7 7 decorator, in order to preserve metadata such as function name, setup and
8 8 teardown functions and so on - see nose.tools for more information.
9 9
10 10 This module provides a set of useful decorators meant to be ready to use in
11 11 your own tests. See the bottom of the file for the ready-made ones, and if you
12 12 find yourself writing a new one that may be of generic use, add it here.
13 13
14 14 Included decorators:
15 15
16 16
17 17 Lightweight testing that remains unittest-compatible.
18 18
19 19 - An @as_unittest decorator can be used to tag any normal parameter-less
20 20 function as a unittest TestCase. Then, both nose and normal unittest will
21 21 recognize it as such. This will make it easier to migrate away from Nose if
22 22 we ever need/want to while maintaining very lightweight tests.
23 23
24 24 NOTE: This file contains IPython-specific decorators. Using the machinery in
25 25 IPython.external.decorators, we import either numpy.testing.decorators if numpy is
26 26 available, OR use equivalent code in IPython.external._decorators, which
27 27 we've copied verbatim from numpy.
28 28
29 29 """
30 30
31 31 # Copyright (c) IPython Development Team.
32 32 # Distributed under the terms of the Modified BSD License.
33 33
34 34 import sys
35 35 import os
36 36 import tempfile
37 37 import unittest
38 38 import warnings
39 39
40 40 from decorator import decorator
41 41
42 42 # Expose the unittest-driven decorators
43 43 from .ipunittest import ipdoctest, ipdocstring
44 44
45 45 # Grab the numpy-specific decorators which we keep in a file that we
46 46 # occasionally update from upstream: decorators.py is a copy of
47 47 # numpy.testing.decorators, we expose all of it here.
48 48 from IPython.external.decorators import *
49 49
50 50 # For onlyif_cmd_exists decorator
51 51 from IPython.utils.py3compat import string_types, which, PY2, PY3, PYPY
52 52
53 53 #-----------------------------------------------------------------------------
54 54 # Classes and functions
55 55 #-----------------------------------------------------------------------------
56 56
57 57 # Simple example of the basic idea
58 58 def as_unittest(func):
59 59 """Decorator to make a simple function into a normal test via unittest."""
60 60 class Tester(unittest.TestCase):
61 61 def test(self):
62 62 func()
63 63
64 64 Tester.__name__ = func.__name__
65 65
66 66 return Tester
67 67
68 68 # Utility functions
69 69
70 70 def apply_wrapper(wrapper,func):
71 71 """Apply a wrapper to a function for decoration.
72 72
73 73 This mixes Michele Simionato's decorator tool with nose's make_decorator,
74 74 to apply a wrapper in a decorator so that all nose attributes, as well as
75 75 function signature and other properties, survive the decoration cleanly.
76 76 This will ensure that wrapped functions can still be well introspected via
77 77 IPython, for example.
78 78 """
79 79 warnings.warn("The function `apply_wrapper` is deprecated and might be removed in IPython 5.0", DeprecationWarning)
80 80
81 81 import nose.tools
82 82
83 83 return decorator(wrapper,nose.tools.make_decorator(func)(wrapper))
84 84
85 85
86 86 def make_label_dec(label,ds=None):
87 87 """Factory function to create a decorator that applies one or more labels.
88 88
89 89 Parameters
90 90 ----------
91 91 label : string or sequence
92 92 One or more labels that will be applied by the decorator to the functions
93 93 it decorates. Labels are attributes of the decorated function with their
94 94 value set to True.
95 95
96 96 ds : string
97 97 An optional docstring for the resulting decorator. If not given, a
98 98 default docstring is auto-generated.
99 99
100 100 Returns
101 101 -------
102 102 A decorator.
103 103
104 104 Examples
105 105 --------
106 106
107 107 A simple labeling decorator:
108 108
109 109 >>> slow = make_label_dec('slow')
110 110 >>> slow.__doc__
111 111 "Labels a test as 'slow'."
112 112
113 113 And one that uses multiple labels and a custom docstring:
114 114
115 115 >>> rare = make_label_dec(['slow','hard'],
116 116 ... "Mix labels 'slow' and 'hard' for rare tests.")
117 117 >>> rare.__doc__
118 118 "Mix labels 'slow' and 'hard' for rare tests."
119 119
120 120 Now, let's test using this one:
121 121 >>> @rare
122 122 ... def f(): pass
123 123 ...
124 124 >>>
125 125 >>> f.slow
126 126 True
127 127 >>> f.hard
128 128 True
129 129 """
130 130
131 131 warnings.warn("The function `make_label_dec` is deprecated and might be removed in IPython 5.0", DeprecationWarning)
132 132 if isinstance(label, string_types):
133 133 labels = [label]
134 134 else:
135 135 labels = label
136 136
137 137 # Validate that the given label(s) are OK for use in setattr() by doing a
138 138 # dry run on a dummy function.
139 139 tmp = lambda : None
140 140 for label in labels:
141 141 setattr(tmp,label,True)
142 142
143 143 # This is the actual decorator we'll return
144 144 def decor(f):
145 145 for label in labels:
146 146 setattr(f,label,True)
147 147 return f
148 148
149 149 # Apply the user's docstring, or autogenerate a basic one
150 150 if ds is None:
151 151 ds = "Labels a test as %r." % label
152 152 decor.__doc__ = ds
153 153
154 154 return decor
155 155
156 156
157 157 # Inspired by numpy's skipif, but uses the full apply_wrapper utility to
158 158 # preserve function metadata better and allows the skip condition to be a
159 159 # callable.
160 160 def skipif(skip_condition, msg=None):
161 161 ''' Make function raise SkipTest exception if skip_condition is true
162 162
163 163 Parameters
164 164 ----------
165 165
166 166 skip_condition : bool or callable
167 167 Flag to determine whether to skip test. If the condition is a
168 168 callable, it is used at runtime to dynamically make the decision. This
169 169 is useful for tests that may require costly imports, to delay the cost
170 170 until the test suite is actually executed.
171 171 msg : string
172 172 Message to give on raising a SkipTest exception.
173 173
174 174 Returns
175 175 -------
176 176 decorator : function
177 177 Decorator, which, when applied to a function, causes SkipTest
178 178 to be raised when the skip_condition was True, and the function
179 179 to be called normally otherwise.
180 180
181 181 Notes
182 182 -----
183 183 You will see from the code that we had to further decorate the
184 184 decorator with the nose.tools.make_decorator function in order to
185 185 transmit function name, and various other metadata.
186 186 '''
187 187
188 188 def skip_decorator(f):
189 189 # Local import to avoid a hard nose dependency and only incur the
190 190 # import time overhead at actual test-time.
191 191 import nose
192 192
193 193 # Allow for both boolean or callable skip conditions.
194 194 if callable(skip_condition):
195 195 skip_val = skip_condition
196 196 else:
197 197 skip_val = lambda : skip_condition
198 198
199 199 def get_msg(func,msg=None):
200 200 """Skip message with information about function being skipped."""
201 201 if msg is None: out = 'Test skipped due to test condition.'
202 202 else: out = msg
203 203 return "Skipping test: %s. %s" % (func.__name__,out)
204 204
205 205 # We need to define *two* skippers because Python doesn't allow both
206 206 # return with value and yield inside the same function.
207 207 def skipper_func(*args, **kwargs):
208 208 """Skipper for normal test functions."""
209 209 if skip_val():
210 210 raise nose.SkipTest(get_msg(f,msg))
211 211 else:
212 212 return f(*args, **kwargs)
213 213
214 214 def skipper_gen(*args, **kwargs):
215 215 """Skipper for test generators."""
216 216 if skip_val():
217 217 raise nose.SkipTest(get_msg(f,msg))
218 218 else:
219 219 for x in f(*args, **kwargs):
220 220 yield x
221 221
222 222 # Choose the right skipper to use when building the actual generator.
223 223 if nose.util.isgenerator(f):
224 224 skipper = skipper_gen
225 225 else:
226 226 skipper = skipper_func
227 227
228 228 return nose.tools.make_decorator(f)(skipper)
229 229
230 230 return skip_decorator
231 231
232 232 # A version with the condition set to true, common case just to attach a message
233 233 # to a skip decorator
234 234 def skip(msg=None):
235 235 """Decorator factory - mark a test function for skipping from test suite.
236 236
237 237 Parameters
238 238 ----------
239 239 msg : string
240 240 Optional message to be added.
241 241
242 242 Returns
243 243 -------
244 244 decorator : function
245 245 Decorator, which, when applied to a function, causes SkipTest
246 246 to be raised, with the optional message added.
247 247 """
248 248
249 249 return skipif(True,msg)
250 250
251 251
252 252 def onlyif(condition, msg):
253 253 """The reverse from skipif, see skipif for details."""
254 254
255 255 if callable(condition):
256 256 skip_condition = lambda : not condition()
257 257 else:
258 258 skip_condition = lambda : not condition
259 259
260 260 return skipif(skip_condition, msg)
261 261
262 262 #-----------------------------------------------------------------------------
263 263 # Utility functions for decorators
264 264 def module_not_available(module):
265 265 """Can module be imported? Returns true if module does NOT import.
266 266
267 267 This is used to make a decorator to skip tests that require module to be
268 268 available, but delay the 'import numpy' to test execution time.
269 269 """
270 270 try:
271 271 mod = __import__(module)
272 272 mod_not_avail = False
273 273 except ImportError:
274 274 mod_not_avail = True
275 275
276 276 return mod_not_avail
277 277
278 278
279 279 def decorated_dummy(dec, name):
280 280 """Return a dummy function decorated with dec, with the given name.
281 281
282 282 Examples
283 283 --------
284 284 import IPython.testing.decorators as dec
285 285 setup = dec.decorated_dummy(dec.skip_if_no_x11, __name__)
286 286 """
287 287 warnings.warn("The function `make_label_dec` is deprecated and might be removed in IPython 5.0", DeprecationWarning)
288 288 dummy = lambda: None
289 289 dummy.__name__ = name
290 290 return dec(dummy)
291 291
292 292 #-----------------------------------------------------------------------------
293 293 # Decorators for public use
294 294
295 295 # Decorators to skip certain tests on specific platforms.
296 296 skip_win32 = skipif(sys.platform == 'win32',
297 297 "This test does not run under Windows")
298 298 skip_linux = skipif(sys.platform.startswith('linux'),
299 299 "This test does not run under Linux")
300 300 skip_osx = skipif(sys.platform == 'darwin',"This test does not run under OS X")
301 301
302 302
303 303 # Decorators to skip tests if not on specific platforms.
304 304 skip_if_not_win32 = skipif(sys.platform != 'win32',
305 305 "This test only runs under Windows")
306 306 skip_if_not_linux = skipif(not sys.platform.startswith('linux'),
307 307 "This test only runs under Linux")
308 308 skip_if_not_osx = skipif(sys.platform != 'darwin',
309 309 "This test only runs under OSX")
310 310
311 311
312 312 _x11_skip_cond = (sys.platform not in ('darwin', 'win32') and
313 313 os.environ.get('DISPLAY', '') == '')
314 314 _x11_skip_msg = "Skipped under *nix when X11/XOrg not available"
315 315
316 316 skip_if_no_x11 = skipif(_x11_skip_cond, _x11_skip_msg)
317 317
318 318 # not a decorator itself, returns a dummy function to be used as setup
319 319 def skip_file_no_x11(name):
320 320 warnings.warn("The function `skip_file_no_x11` is deprecated and might be removed in IPython 5.0", DeprecationWarning)
321 321 return decorated_dummy(skip_if_no_x11, name) if _x11_skip_cond else None
322 322
323 323 # Other skip decorators
324 324
325 325 # generic skip without module
326 326 skip_without = lambda mod: skipif(module_not_available(mod), "This test requires %s" % mod)
327 327
328 328 skipif_not_numpy = skip_without('numpy')
329 329
330 330 skipif_not_matplotlib = skip_without('matplotlib')
331 331
332 332 skipif_not_sympy = skip_without('sympy')
333 333
334 334 skip_known_failure = knownfailureif(True,'This test is known to fail')
335 335
336 336 known_failure_py3 = knownfailureif(sys.version_info[0] >= 3,
337 337 'This test is known to fail on Python 3.')
338 338
339 cpython2_only = skipif(PY3 or PYPY, "This test only runs on CPython 2.")
340 339 py2_only = skipif(PY3, "This test only runs on Python 2.")
341 340 py3_only = skipif(PY2, "This test only runs on Python 3.")
342 341
343 342 # A null 'decorator', useful to make more readable code that needs to pick
344 343 # between different decorators based on OS or other conditions
345 344 null_deco = lambda f: f
346 345
347 346 # Some tests only run where we can use unicode paths. Note that we can't just
348 347 # check os.path.supports_unicode_filenames, which is always False on Linux.
349 348 try:
350 349 f = tempfile.NamedTemporaryFile(prefix=u"tmp€")
351 350 except UnicodeEncodeError:
352 351 unicode_paths = False
353 352 else:
354 353 unicode_paths = True
355 354 f.close()
356 355
357 356 onlyif_unicode_paths = onlyif(unicode_paths, ("This test is only applicable "
358 357 "where we can use unicode in filenames."))
359 358
360 359
361 360 def onlyif_cmds_exist(*commands):
362 361 """
363 362 Decorator to skip test when at least one of `commands` is not found.
364 363 """
365 364 for cmd in commands:
366 365 if not which(cmd):
367 366 return skip("This test runs only if command '{0}' "
368 367 "is installed".format(cmd))
369 368 return null_deco
370 369
371 370 def onlyif_any_cmd_exists(*commands):
372 371 """
373 372 Decorator to skip test unless at least one of `commands` is found.
374 373 """
375 374 warnings.warn("The function `onlyif_any_cmd_exists` is deprecated and might be removed in IPython 5.0", DeprecationWarning)
376 375 for cmd in commands:
377 376 if which(cmd):
378 377 return null_deco
379 378 return skip("This test runs only if one of the commands {0} "
380 379 "is installed".format(commands))
General Comments 0
You need to be logged in to leave comments. Login now