1"""
2Helper code for implementing unittests.
3
4This module is unsupported and is primairily used in the PyObjC
5testsuite.
6"""
7import plistlib as _pl
8import unittest as _unittest
9import objc
10import os as _os
11import gc as _gc
12import subprocess as _subprocess
13import sys as _sys
14import struct as _struct
15from distutils.sysconfig import get_config_var as _get_config_var
16import re as _re
17import warnings
18
19# Have a way to disable the autorelease pool behaviour
20_usepool = not _os.environ.get('PYOBJC_NO_AUTORELEASE')
21_useleaks = bool(_os.environ.get('PyOBJC_USE_LEAKS'))
22_leaksVerbose = True
23
24def _typemap(tp):
25    return tp.replace('_NSRect', 'CGRect').replace('_NSPoint', 'CGPoint').replace('_NSSize', 'CGSize')
26
27def sdkForPython(_cache=[]):
28    """
29    Return the SDK version used to compile Python itself,
30    or None if no framework was used
31    """
32    if not _cache:
33
34        cflags = _get_config_var('CFLAGS')
35        m = _re.search('-isysroot ([^ ]*) ', cflags)
36        if m is None:
37            return None
38
39
40        path = m.group(1)
41        if path == '/':
42            return tuple(map(int, os_release().split('.')))
43
44        bn = _os.path.basename(path)
45        version = bn[6:-4]
46        if version.endswith('u'):
47            version = version[:-1]
48
49
50        return tuple(map(int, version.split('.')))
51
52    return _cache[0]
53
54def fourcc(v):
55    """
56    Decode four-character-code integer definition
57
58    (e.g. 'abcd')
59    """
60    return _struct.unpack('>i', v)[0]
61
62def cast_int(value):
63    """
64    Cast value to 32bit integer
65
66    Usage:
67        cast_int(1 << 31) == -1
68
69    (where as: 1 << 31 == 2147483648)
70    """
71    value = value & 0xffffffff
72    if value & 0x80000000:
73        value =   ~value + 1 & 0xffffffff
74        return -value
75    else:
76        return value
77
78_os_release = None
79def os_release():
80    """
81    Returns '10.5' on all releases of Leopard, simularly for other
82    major releases.
83    """
84    global _os_release
85    if _os_release is not None:
86        return _os_release
87
88    pl = _pl.readPlist('/System/Library/CoreServices/SystemVersion.plist')
89    v = pl['ProductVersion']
90    return '.'.join(v.split('.')[:2])
91
92
93def is32Bit():
94    """
95    Return True if we're running in 32-bit mode
96    """
97    if hasattr(_sys, 'maxint'):
98        # Python 2.5 or earlier
99        if _sys.maxint > 2 ** 32:
100            return False
101    else:
102        if _sys.maxsize > 2 ** 32:
103            return False
104    return True
105
106def onlyIf(expr, message=None):
107    """
108    Usage::
109
110        class Tests (unittest.TestCase):
111
112            @onlyIf(1 == 2)
113            def testUnlikely(self):
114                pass
115
116    The test only runs when the argument expression is true
117    """
118    def callback(function):
119        if not expr:
120            if hasattr(_unittest, 'skip'):
121                return _unittest.skip(message)(function)
122            return lambda self: None
123        else:
124            return function
125    return callback
126
127def onlyPython2(function):
128    """
129    Usage:
130        class Tests (unittest.TestCase):
131
132            @onlyPython2
133            def testPython2(self):
134                pass
135
136    The test is only executed for Python 2.x
137    """
138    return onlyIf(_sys.version_info[0] == 2, "python2.x only")(function)
139
140def onlyPython3(function):
141    """
142    Usage:
143        class Tests (unittest.TestCase):
144
145            @onlyPython3
146            def testPython3(self):
147                pass
148
149    The test is only executed for Python 3.x
150    """
151    return onlyIf(_sys.version_info[0] == 3, "python3.x only")(function)
152
153def onlyOn32Bit(function):
154    """
155    Usage::
156
157        class Tests (unittest.TestCase):
158
159            @onlyOn32Bit
160            def test32BitOnly(self):
161                pass
162
163    The test runs only on 32-bit systems
164    """
165    return onlyIf(is32Bit(), "32-bit only")(function)
166
167def onlyOn64Bit(function):
168    """
169    Usage::
170
171        class Tests (unittest.TestCase):
172
173            @onlyOn64Bit
174            def test64BitOnly(self):
175                pass
176
177    The test runs only on 64-bit systems
178    """
179    return onlyIf(not is32Bit(), "64-bit only")(function)
180
181
182def min_os_level(release):
183    """
184    Usage::
185
186        class Tests (unittest.TestCase):
187
188            @min_os_level('10.6')
189            def testSnowLeopardCode(self):
190                pass
191    """
192    if os_release() >= release:
193        def decorator(function):
194            return function
195
196    else:
197        if _sys.version_info[:2] >= (2, 7):
198            return _unittest.skip("min_os_level(%s)"%(release,))
199        else:
200            return lambda self: None
201
202    return decorator
203
204def max_os_level(release):
205    """
206    Usage::
207
208        class Tests (unittest.TestCase):
209
210            @max_os_level('10.5')
211            def testUntilLeopard(self):
212                pass
213    """
214    if os_release() <= release:
215        def decorator(function):
216            return function
217
218    else:
219        if _sys.version_info[:2] >= (2, 7):
220            return _unittest.skip("max_os_level(%s)"%(release,))
221        else:
222            return lambda self: None
223
224    return decorator
225
226
227
228def _leaks():
229    data = _subprocess.Popen(
230            ['/usr/bin/leaks', str(_os.getpid())], stdout=_subprocess.PIPE
231        ).communicate()[0]
232    return data.splitlines()
233
234
235_poolclass = objc.lookUpClass('NSAutoreleasePool')
236_nscftype = objc.lookUpClass('NSCFType')
237
238class TestCase (_unittest.TestCase):
239    """
240    A version of TestCase that wraps every test into its own
241    autorelease pool.
242
243    This also adds a number of useful assertion methods
244    """
245
246    def assertGreaterThan(self, value, test, message = None):
247        if not (value > test):
248            self.fail(message or "not: %s > %s"%(value, test))
249
250    def assertGreaterThanOrEquals(self, value, test, message = None):
251        if not (value >= test):
252            self.fail(message or "not: %s >= %s"%(value, test))
253
254    def assertLessThan(self, value, test, message = None):
255        if not (value < test):
256            self.fail(message or "not: %s < %s"%(value, test))
257
258    def assertLessThanOrEquals(self, value, test, message = None):
259        if not (value <= test):
260            self.fail(message or "not: %s <= %s"%(value, test))
261
262    def assertIsCFType(self, tp, message = None):
263        if not isinstance(tp, objc.objc_class):
264            self.fail(message or "%r is not a CFTypeRef type"%(tp,))
265
266        if tp is _nscftype:
267            self.fail(message or "%r is not a unique CFTypeRef type"%(tp,))
268
269
270    def assertIsOpaquePointer(self, tp, message = None):
271        if not hasattr(tp, "__pointer__"):
272            self.fail(message or "%r is not an opaque-pointer"%(tp,))
273
274        if not hasattr(tp, "__typestr__"):
275            self.fail(message or "%r is not an opaque-pointer"%(tp,))
276
277    def assertIs(self, value, test, message = None):
278        if value is not test:
279            self.fail(message or  "%r (id=%r) is not %r (id=%r) "%(value, id(value), test, id(test)))
280
281    def assertIsNot(self, value, test, message = None):
282        if value is test:
283            self.fail(message or  "%r is %r"%(value, test))
284
285    def assertIsNone(self, value, message = None):
286        self.assertIs(value, None)
287
288    def assertIsNotNone(self, value, message = None):
289        if value is None:
290            sel.fail(message, "%r is not %r"%(value, test))
291
292    def assertResultIsNullTerminated(self, method, message = None):
293        info = method.__metadata__()
294        if not info['retval'].get('c_array_delimited_by_null'):
295            self.fail(message or "argument %d of %r is not a nul-terminated array"%(argno, method))
296
297    def assertIsNullTerminated(self, method, message = None):
298        info = method.__metadata__()
299        if not info.get('c_array_delimited_by_null') or not info.get('variadic'):
300            self.fail(message or "%s is not a variadic function with a null-terminated list of arguments"%(method,))
301
302    def assertArgIsNullTerminated(self, method, argno, message = None):
303        if isinstance(method, objc.selector):
304            offset = 2
305        else:
306            offset = 0
307        info = method.__metadata__()
308        if not info['arguments'][argno+offset].get('c_array_delimited_by_null'):
309            self.fail(message or "argument %d of %r is not a nul-terminated array"%(argno, method))
310
311    def assertArgIsVariableSize(self, method, argno, message = None):
312        if isinstance(method, objc.selector):
313            offset = 2
314        else:
315            offset = 0
316        info = method.__metadata__()
317        if not info['arguments'][argno+offset].get('c_array_of_variable_length'):
318            self.fail(message or "argument %d of %r is not a variable sized array"%(argno, method))
319
320    def assertResultIsVariableSize(self, method, message = None):
321        info = method.__metadata__()
322        if not info['retval'].get('c_array_of_variable_length'):
323            self.fail(message or "result of %r is not a variable sized array"%(argno, method))
324
325    def assertArgSizeInResult(self, method, argno, message = None):
326        if isinstance(method, objc.selector):
327            offset = 2
328        else:
329            offset = 0
330        info = method.__metadata__()
331        if not info['arguments'][argno+offset].get('c_array_length_in_result'):
332            self.fail(message or "argument %d of %r does not have size in result"%(argno, method))
333
334    def assertArgIsPrintf(self, method, argno, message = None):
335        if isinstance(method, objc.selector):
336            offset = 2
337        else:
338            offset = 0
339        info = method.__metadata__()
340        if not info.get('variadic'):
341            self.fail(message or "%r is not a variadic function"%(method,))
342
343        if not info['arguments'][argno+offset].get('printf_format'):
344            self.fail(message or "%r argument %d is not a printf format string"%(method, argno))
345
346    def assertArgIsCFRetained(self, method, argno, message = None):
347        if isinstance(method, objc.selector):
348            offset = 2
349        else:
350            offset = 0
351        info = method.__metadata__()
352        if not info['arguments'][argno+offset]['already_cfretained']:
353            self.fail(message or "%r is not cfretained"%(method,))
354
355    def assertArgIsNotCFRetained(self, method, argno, message = None):
356        if isinstance(method, objc.selector):
357            offset = 2
358        else:
359            offset = 0
360        info = method.__metadata__()
361        if info['arguments'][argno+offset]['already_cfretained']:
362            self.fail(message or "%r is cfretained"%(method,))
363
364    def assertResultIsCFRetained(self, method, message = None):
365        info = method.__metadata__()
366        if not info['retval']['already_cfretained']:
367            self.fail(message or "%r is not cfretained"%(method,))
368
369    def assertResultIsNotCFRetained(self, method, message = None):
370        info = method.__metadata__()
371        if info['retval']['already_cfretained']:
372            self.fail(message or "%r is cfretained"%(method,))
373
374    def assertResultIsRetained(self, method, message = None):
375        info = method.__metadata__()
376        if not info['retval']['already_retained']:
377            self.fail(message or "%r is not retained"%(method,))
378
379    def assertResultIsNotRetained(self, method, message = None):
380        info = method.__metadata__()
381        if info['retval']['already_retained']:
382            self.fail(message or "%r is retained"%(method,))
383
384    def assertResultHasType(self, method, tp, message=None):
385        info = method.__metadata__()
386        type = info['retval']['type']
387        if type != tp and _typemap(type) != _typemap(tp):
388            self.fail(message or "result of %r is not of type %r, but %r"%(
389                method, tp, type))
390
391    def assertArgHasType(self, method, argno, tp, message=None):
392        if isinstance(method, objc.selector):
393            offset = 2
394        else:
395            offset = 0
396        info = method.__metadata__()
397        type = info['arguments'][argno+offset]['type']
398        if type != tp and _typemap(type) != _typemap(tp):
399            self.fail(message or "arg %d of %s is not of type %r, but %r"%(
400                argno, method, tp, type))
401
402    def assertArgIsFunction(self, method, argno, sel_type, retained, message=None):
403        if isinstance(method, objc.selector):
404            offset = 2
405        else:
406            offset = 0
407        info = method.__metadata__()
408        type = info['arguments'][argno+offset]['type']
409        if type != b'^?':
410            self.fail(message or "arg %d of %s is not of type function_pointer"%(
411                argno, method))
412
413        st = info['arguments'][argno+offset].get('callable')
414        if st is None:
415            self.fail(message or "arg %d of %s is not of type function_pointer"%(
416                argno, method))
417
418        iface = st['retval']['type']
419        for a in st['arguments']:
420            iface += a['type']
421
422        if iface != sel_type:
423            self.fail(message or "arg %d of %s is not a function_pointer with type %r, but %r"%(argno, method, sel_type, iface))
424
425
426        st = info['arguments'][argno+offset]['callable_retained']
427        if bool(st) != bool(retained):
428            self.fail(message or "arg %d of %s; retained: %r, expected: %r"%(
429                argno, method, st, retained))
430
431    def assertArgIsBlock(self, method, argno, sel_type, message=None):
432        if isinstance(method, objc.selector):
433            offset = 2
434        else:
435            offset = 0
436        info = method.__metadata__()
437        type = info['arguments'][argno+offset]['type']
438        if type != b'@?':
439            self.fail(message or "arg %d of %s is not of type block: %s"%(
440                argno, method, type))
441
442        st = info['arguments'][argno+offset].get('callable')
443        if st is None:
444            self.fail(message or "arg %d of %s is not of type block: no callable"%(
445                argno, method))
446
447        iface = st['retval']['type']
448        if st['arguments'][0]['type'] != b'^v':
449            self.fail(message or "arg %d of %s has an invalid block signature"%(argno, method))
450        for a in st['arguments'][1:]:
451            iface += a['type']
452
453        if iface != sel_type:
454            self.fail(message or "arg %d of %s is not a block with type %r, but %r"%(argno, method, sel_type, iface))
455
456    def assertResultIsBlock(self, method, sel_type, message=None):
457        info = method.__metadata__()
458        type = info['retval']['type']
459        if type != b'@?':
460            self.fail(message or "result of %s is not of type block"%(
461                method))
462
463        st = info['retval'].get('callable')
464        if st is None:
465            self.fail(message or "result of %s is not of type block"%(
466                method))
467
468        iface = st['retval']['type']
469        if st['arguments'][0]['type'] != b'^v':
470            self.fail(message or "result %s has an invalid block signature"%(method))
471        for a in st['arguments'][1:]:
472            iface += a['type']
473
474        if iface != sel_type:
475            self.fail(message or "result of %s is not a block with type %r, but %r"%(method, sel_type, iface))
476
477    def assertArgIsSEL(self, method, argno, sel_type, message=None):
478        if isinstance(method, objc.selector):
479            offset = 2
480        else:
481            offset = 0
482        info = method.__metadata__()
483        type = info['arguments'][argno+offset]['type']
484        if type != objc._C_SEL:
485            self.fail(message or "arg %d of %s is not of type SEL"%(
486                argno, method))
487
488        st = info['arguments'][argno+offset].get('sel_of_type')
489        if st != sel_type and _typemap(st) != _typemap(sel_type):
490            self.fail(message or "arg %d of %s doesn't have sel_type %r but %r"%(
491                argno, method, sel_type, st))
492
493    def assertResultIsBOOL(self, method, message=None):
494        info = method.__metadata__()
495        type = info['retval']['type']
496        if type != objc._C_NSBOOL:
497            self.fail(message or "result of %s is not of type BOOL, but %r"%(
498                method, type))
499
500    def assertArgIsBOOL(self, method, argno, message=None):
501        if isinstance(method, objc.selector):
502            offset = 2
503        else:
504            offset = 0
505        info = method.__metadata__()
506        type = info['arguments'][argno+offset]['type']
507        if type != objc._C_NSBOOL:
508            self.fail(message or "arg %d of %s is not of type BOOL, but %r"%(
509                argno, method, type))
510
511    def assertArgIsFixedSize(self, method, argno, count, message=None):
512        if isinstance(method, objc.selector):
513            offset = 2
514        else:
515            offset = 0
516        info = method.__metadata__()
517        cnt = info['arguments'][argno+offset]['c_array_of_fixed_length']
518        if cnt != count:
519            self.fail(message or "arg %d of %s is not a C-array of length %d"%(
520                argno, method, count))
521
522    def assertArgSizeInArg(self, method, argno, count, message=None):
523        if isinstance(method, objc.selector):
524            offset = 2
525        else:
526            offset = 0
527        info = method.__metadata__()
528        cnt = info['arguments'][argno+offset]['c_array_length_in_arg']
529        if isinstance(count, (list, tuple)):
530            count2 = tuple(x + offset for x in count)
531        else:
532            count2 = count + offset
533        if cnt != count2:
534            self.fail(message or "arg %d of %s is not a C-array of with length in arg %d"%(
535                argno, method, count))
536
537    def assertResultSizeInArg(self, method, count, message=None):
538        if isinstance(method, objc.selector):
539            offset = 2
540        else:
541            offset = 0
542        info = method.__metadata__()
543        cnt = info['retval']['c_array_length_in_arg']
544        if cnt != count + offset:
545            self.fail(message or "result %s is not a C-array of with length in arg %d"%(
546                argno, method, count))
547
548
549    def assertArgIsOut(self, method, argno, message=None):
550        if isinstance(method, objc.selector):
551            offset = 2
552        else:
553            offset = 0
554        info = method.__metadata__()
555        type = info['arguments'][argno+offset]['type']
556        if not type.startswith(b'o^'):
557            self.fail(message or "arg %d of %s is not an 'out' argument"%(
558                argno, method))
559
560    def assertArgIsInOut(self, method, argno, message=None):
561        if isinstance(method, objc.selector):
562            offset = 2
563        else:
564            offset = 0
565        info = method.__metadata__()
566        type = info['arguments'][argno+offset]['type']
567        if not type.startswith(b'N^'):
568            self.fail(message or "arg %d of %s is not an 'inout' argument"%(
569                argno, method))
570
571    def assertArgIsIn(self, method, argno, message=None):
572        if isinstance(method, objc.selector):
573            offset = 2
574        else:
575            offset = 0
576        info = method.__metadata__()
577        type = info['arguments'][argno+offset]['type']
578        if not type.startswith(b'n^'):
579            self.fail(message or "arg %d of %s is not an 'in' argument"%(
580                argno, method))
581
582
583    def assertStartswith(self, value, check, message=None):
584        if not value.startswith(check):
585            self.fail(message or "not %r.startswith(%r)"%(value, check))
586
587    def assertHasAttr(self, value, key, message=None):
588        if not hasattr(value, key):
589            self.fail(message or "%s is not an attribute of %r"%(key, value))
590
591    def assertNotHasAttr(self, value, key, message=None):
592        if hasattr(value, key):
593            self.fail(message or "%s is an attribute of %r"%(key, value))
594
595    def assertIsInstance(self, value, types, message=None):
596        if not isinstance(value, types):
597            self.fail(message or "%s is not an instance of %r but %s"%(value, types, type(value)))
598
599    def assertIsNotInstance(self, value, types, message=None):
600        if isinstance(value, types):
601            self.fail(message or "%s is an instance of %r"%(value, types))
602
603    def assertIn(self, value, seq, message=None):
604        if value not in seq:
605            self.fail(message or "%r is not in %r"%(value, seq))
606
607    def assertNotIn(self, value, seq, message=None):
608        if value in seq:
609            self.fail(message or "%r is in %r"%(value, seq))
610
611
612    if not hasattr(_unittest.TestCase, 'assertGreaterThan'):
613        def assertGreaterThan(self, val, test, message=None):
614            if not (val > test):
615                self.fail(message or '%r <= %r'%(val, test))
616
617    if not hasattr(_unittest.TestCase, 'assertGreaterEqual'):
618        def assertGreaterEqual(self, val, test, message=None):
619            if not (val >= test):
620                self.fail(message or '%r < %r'%(val, test))
621
622    if not hasattr(_unittest.TestCase, 'assertLessThan'):
623        def assertLessThan(self, val, test, message=None):
624            if not (val < test):
625                self.fail(message or '%r >= %r'%(val, test))
626
627    if not hasattr(_unittest.TestCase, 'assertLessEqual'):
628        def assertLessEqual(self, val, test, message=None):
629            if not (val <= test):
630                self.fail(message or '%r > %r'%(val, test))
631
632
633    if not hasattr(_unittest.TestCase, "assertAlmostEquals"):
634        def assertAlmostEquals(self, val1, val2, message=None):
635            self.failUnless(abs (val1 - val2) < 0.00001,
636                    message or 'abs(%r - %r) >= 0.00001'%(val1, val2))
637
638
639    def run(self, *args):
640        if _useleaks:
641            leaksBefore = _leaks()
642        if _usepool:
643            p = _poolclass.alloc().init()
644        else:
645            p = 1
646
647        try:
648            _unittest.TestCase.run(self, *args)
649        finally:
650            _gc.collect()
651            del p
652            _gc.collect()
653
654            if _useleaks:
655                leaksAfter = _leaks()
656                if len(leaksBefore) != len(leaksAfter):
657                    print "\ntest %s is leaking [%d lines]"%(self, len(leaksAfter) - len(leaksBefore))
658                    if _leaksVerbose:
659                        # XXX: add a smartish filter the surpresses the leaks
660                        # in leaksBefore.
661                        for ln in leaksAfter:
662                            print ln
663
664    def _deprecate(original_func):
665        def deprecated_func(*args, **kwds):
666            warnings.warn("Please use %s instead."%(original_func.__name__,),
667                    DeprecationWarning, 2)
668            return original_func(*args, **kwds)
669        return deprecated_func
670
671    failUnlessIsIn = _deprecate(assertIn)
672    failUnlessIsNotIn = _deprecate(assertNotIn)
673    assertIsIn = _deprecate(assertIn)
674    assertIsNotIn = _deprecate(assertNotIn)
675    failUnlessIsCFType = _deprecate(assertIsCFType)
676    failUnlessIsOpaquePointer = _deprecate(assertIsOpaquePointer)
677    failUnlessIsNone = _deprecate(assertIsNone)
678    failIfIsNone = _deprecate(assertIsNotNone)
679    failUnlessResultIsNullTerminated = _deprecate(assertResultIsNullTerminated)
680    failUnlessIsNullTerminated = _deprecate(assertIsNullTerminated)
681    failUnlessArgIsNullTerminated = _deprecate(assertArgIsNullTerminated)
682    failUnlessArgIsVariableSize = _deprecate(assertArgIsVariableSize)
683    failUnlessResultIsVariableSize = _deprecate(assertResultIsVariableSize)
684    failUnlessArgSizeInResult = _deprecate(assertArgSizeInResult)
685    failUnlessArgIsPrintf = _deprecate(assertArgIsPrintf)
686    failUnlessArgIsCFRetained = _deprecate(assertArgIsCFRetained)
687    failIfArgIsCFRetained = _deprecate(assertArgIsCFRetained)
688    failUnlessResultIsCFRetained = _deprecate(assertResultIsCFRetained)
689    failIfResultIsCFRetained = _deprecate(assertResultIsNotCFRetained)
690    failUnlessResultIsRetained = _deprecate(assertResultIsRetained)
691    failIfResultIsRetained = _deprecate(assertResultIsNotRetained)
692    failUnlessResultHasType = _deprecate(assertResultHasType)
693    failUnlessArgHasType = _deprecate(assertArgHasType)
694    failUnlessArgIsFunction = _deprecate(assertArgIsFunction)
695    failUnlessArgIsBlock = _deprecate(assertArgIsBlock)
696    failUnlessResultIsBlock = _deprecate(assertResultIsBlock)
697    failUnlessArgIsSEL = _deprecate(assertArgIsSEL)
698    failUnlessResultIsBOOL = _deprecate(assertResultIsBOOL)
699    failUnlessArgIsBOOL = _deprecate(assertArgIsBOOL)
700    failUnlessArgIsFixedSize = _deprecate(assertArgIsFixedSize)
701    failUnlessArgSizeInArg = _deprecate(assertArgSizeInArg)
702    failUnlessResultSizeInArg = _deprecate(assertResultSizeInArg)
703    failUnlessArgIsOut = _deprecate(assertArgIsOut)
704    failUnlessArgIsInOut = _deprecate(assertArgIsInOut)
705    failUnlessArgIsIn = _deprecate(assertArgIsIn)
706    failUnlessStartswith = _deprecate(assertStartswith)
707    failUnlessHasAttr = _deprecate(assertHasAttr)
708    failIfHasAttr = _deprecate(assertNotHasAttr)
709    failUnlessIsInstance = _deprecate(assertIsInstance)
710    failIfIsInstance = _deprecate(assertIsNotInstance)
711    failUnlessIsIn = _deprecate(assertIsIn)
712    failIfIsNotIn = _deprecate(assertIsIn)
713    failUnlessIsNotIn = _deprecate(assertIsNotIn)
714    failIfIsIn = _deprecate(assertIsNotIn)
715    assertNotIsInstance = _deprecate(assertIsNotInstance)
716    assertIsObject = _deprecate(assertIs)
717    assertIsNotObject = _deprecate(assertIsNot)
718
719    del _deprecate
720
721main = _unittest.main
722
723if hasattr(_unittest, 'expectedFailure'):
724    expectedFailure = _unittest.expectedFailure
725else:
726    def expectedFailure(func):
727        def test(self):
728            try:
729                func(self)
730
731            except AssertionError:
732                return
733
734            self.fail("test unexpectedly passed")
735        test.__name__ == func.__name__
736
737        return test
738
739