Code

Ticket #15828: unittest-django-vs-python-2.7.2.diff

File unittest-django-vs-python-2.7.2.diff, 55.4 KB (added by aaugustin, 2 years ago)
Line 
1diff -u -Naur -x .svn -x .DS_Store -x test -x '*.pyc' -w django/utils/unittest/__init__.py /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/__init__.py
2--- django/utils/unittest/__init__.py   2011-07-10 18:42:06.000000000 +0200
3+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/__init__.py  2011-06-11 15:50:36.000000000 +0200
4@@ -1,12 +1,30 @@
5 """
6-unittest2
7+Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's
8+Smalltalk testing framework.
9 
10-unittest2 is a backport of the new features added to the unittest testing
11-framework in Python 2.7. It is tested to run on Python 2.4 - 2.6.
12+This module contains the core framework classes that form the basis of
13+specific test cases and suites (TestCase, TestSuite etc.), and also a
14+text-based utility class for running the tests and reporting the results
15+ (TextTestRunner).
16 
17-To use unittest2 instead of unittest simply replace ``import unittest`` with
18-``import unittest2``.
19+Simple usage:
20 
21+    import unittest
22+
23+    class IntegerArithmenticTestCase(unittest.TestCase):
24+        def testAdd(self):  ## test method names begin 'test*'
25+            self.assertEqual((1 + 2), 3)
26+            self.assertEqual(0 + 1, 1)
27+        def testMultiply(self):
28+            self.assertEqual((0 * 10), 0)
29+            self.assertEqual((5 * 8), 40)
30+
31+    if __name__ == '__main__':
32+        unittest.main()
33+
34+Further information is available in the bundled documentation, and from
35+
36+  http://docs.python.org/library/unittest.html
37 
38 Copyright (c) 1999-2003 Steve Purcell
39 Copyright (c) 2003-2010 Python Software Foundation
40@@ -26,55 +44,26 @@
41 SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
42 """
43 
44-import sys
45-
46-# Django hackery to load the appropriate version of unittest
47-
48-try:
49-    # check the system path first
50-    from unittest2 import *
51-except ImportError:
52-    if sys.version_info >= (2,7):
53-        # unittest2 features are native in Python 2.7
54-        from unittest import *
55-    else:
56-        # otherwise use our bundled version
57         __all__ = ['TestResult', 'TestCase', 'TestSuite',
58                    'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main',
59                    'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless',
60-                   'expectedFailure', 'TextTestResult', '__version__', 'collector']
61-
62-        __version__ = '0.5.1'
63+           'expectedFailure', 'TextTestResult', 'installHandler',
64+           'registerResult', 'removeResult', 'removeHandler']
65 
66         # Expose obsolete functions for backwards compatibility
67         __all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
68 
69+__unittest = True
70 
71-        from django.utils.unittest.collector import collector
72-        from django.utils.unittest.result import TestResult
73-        from django.utils.unittest.case import \
74-            TestCase, FunctionTestCase, SkipTest, skip, skipIf,\
75-            skipUnless, expectedFailure
76-
77-        from django.utils.unittest.suite import BaseTestSuite, TestSuite
78-        from django.utils.unittest.loader import \
79-            TestLoader, defaultTestLoader, makeSuite, getTestCaseNames,\
80-            findTestCases
81-
82-        from django.utils.unittest.main import TestProgram, main, main_
83-        from django.utils.unittest.runner import TextTestRunner, TextTestResult
84-
85-        try:
86-            from django.utils.unittest.signals import\
87-                installHandler, registerResult, removeResult, removeHandler
88-        except ImportError:
89-            # Compatibility with platforms that don't have the signal module
90-            pass
91-        else:
92-            __all__.extend(['installHandler', 'registerResult', 'removeResult',
93-                            'removeHandler'])
94+from .result import TestResult
95+from .case import (TestCase, FunctionTestCase, SkipTest, skip, skipIf,
96+                   skipUnless, expectedFailure)
97+from .suite import BaseTestSuite, TestSuite
98+from .loader import (TestLoader, defaultTestLoader, makeSuite, getTestCaseNames,
99+                     findTestCases)
100+from .main import TestProgram, main
101+from .runner import TextTestRunner, TextTestResult
102+from .signals import installHandler, registerResult, removeResult, removeHandler
103 
104         # deprecated
105         _TextTestResult = TextTestResult
106-
107-        __unittest = True
108diff -u -Naur -x .svn -x .DS_Store -x test -x '*.pyc' -w django/utils/unittest/__main__.py /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/__main__.py
109--- django/utils/unittest/__main__.py   2011-05-04 23:17:48.000000000 +0200
110+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/__main__.py  2011-06-11 15:50:36.000000000 +0200
111@@ -2,9 +2,11 @@
112 
113 import sys
114 if sys.argv[0].endswith("__main__.py"):
115-    sys.argv[0] = "unittest2"
116+    sys.argv[0] = "python -m unittest"
117 
118 __unittest = True
119 
120-from django.utils.unittest.main import main_
121-main_()
122+from .main import main, TestProgram, USAGE_AS_MAIN
123+TestProgram.USAGE = USAGE_AS_MAIN
124+
125+main(module=None)
126diff -u -Naur -x .svn -x .DS_Store -x test -x '*.pyc' -w django/utils/unittest/case.py /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/case.py
127--- django/utils/unittest/case.py       2011-07-10 20:15:49.000000000 +0200
128+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/case.py      2011-06-11 15:50:36.000000000 +0200
129@@ -1,18 +1,19 @@
130 """Test case implementation"""
131 
132+import collections
133 import sys
134+import functools
135 import difflib
136 import pprint
137 import re
138-import unittest
139 import warnings
140 
141-from django.utils.unittest import result
142-from django.utils.unittest.util import\
143-    safe_repr, safe_str, strclass,\
144-    unorderable_list_difference
145+from . import result
146+from .util import (
147+    strclass, safe_repr, unorderable_list_difference,
148+    _count_diff_all_purpose, _count_diff_hashable
149+)
150 
151-from django.utils.unittest.compatibility import wraps
152 
153 __unittest = True
154 
155@@ -27,6 +28,7 @@
156     Usually you can use TestResult.skip() or one of the skipping decorators
157     instead of raising this directly.
158     """
159+    pass
160 
161 class _ExpectedFailure(Exception):
162     """
163@@ -36,14 +38,14 @@
164     """
165 
166     def __init__(self, exc_info):
167-        # can't use super because Python 2.4 exceptions are old style
168-        Exception.__init__(self)
169+        super(_ExpectedFailure, self).__init__()
170         self.exc_info = exc_info
171 
172 class _UnexpectedSuccess(Exception):
173     """
174     The test was supposed to fail, but it didn't!
175     """
176+    pass
177 
178 def _id(obj):
179     return obj
180@@ -54,7 +56,7 @@
181     """
182     def decorator(test_item):
183         if not (isinstance(test_item, type) and issubclass(test_item, TestCase)):
184-            @wraps(test_item)
185+            @functools.wraps(test_item)
186             def skip_wrapper(*args, **kwargs):
187                 raise SkipTest(reason)
188             test_item = skip_wrapper
189@@ -82,7 +84,7 @@
190 
191 
192 def expectedFailure(func):
193-    @wraps(func)
194+    @functools.wraps(func)
195     def wrapper(*args, **kwargs):
196         try:
197             func(*args, **kwargs)
198@@ -110,7 +112,7 @@
199             except AttributeError:
200                 exc_name = str(self.expected)
201             raise self.failureException(
202-                "%s not raised" % (exc_name,))
203+                "{0} not raised".format(exc_name))
204         if not issubclass(exc_type, self.expected):
205             # let unexpected exceptions pass through
206             return False
207@@ -127,28 +129,7 @@
208         return True
209 
210 
211-class _TypeEqualityDict(object):
212-
213-    def __init__(self, testcase):
214-        self.testcase = testcase
215-        self._store = {}
216-
217-    def __setitem__(self, key, value):
218-        self._store[key] = value
219-
220-    def __getitem__(self, key):
221-        value = self._store[key]
222-        if isinstance(value, basestring):
223-            return getattr(self.testcase, value)
224-        return value
225-
226-    def get(self, key, default=None):
227-        if key in self._store:
228-            return self[key]
229-        return default
230-
231-
232-class TestCase(unittest.TestCase):
233+class TestCase(object):
234     """A class whose instances are single test cases.
235 
236     By default, the test code itself should be placed in a method named
237@@ -176,17 +157,21 @@
238 
239     failureException = AssertionError
240 
241+    # This attribute determines whether long messages (including repr of
242+    # objects used in assert methods) will be printed on failure in *addition*
243+    # to any explicit message passed.
244+
245+    longMessage = False
246+
247     # This attribute sets the maximum length of a diff in failure messages
248     # by assert methods using difflib. It is looked up as an instance attribute
249     # so can be configured by individual tests if required.
250 
251     maxDiff = 80*8
252 
253-    # This attribute determines whether long messages (including repr of
254-    # objects used in assert methods) will be printed on failure in *addition*
255-    # to any explicit message passed.
256-
257-    longMessage = True
258+    # If a string is longer than _diffThreshold, use normal comparison instead
259+    # of difflib.  See #11763.
260+    _diffThreshold = 2**16
261 
262     # Attribute used by TestSuite for classSetUp
263 
264@@ -202,7 +187,7 @@
265         try:
266             testMethod = getattr(self, methodName)
267         except AttributeError:
268-            raise ValueError("no such test method in %s: %s" % \
269+            raise ValueError("no such test method in %s: %s" %
270                   (self.__class__, methodName))
271         self._testMethodDoc = testMethod.__doc__
272         self._cleanups = []
273@@ -210,13 +195,13 @@
274         # Map types to custom assertEqual functions that will compare
275         # instances of said type in more detail to generate a more useful
276         # error message.
277-        self._type_equality_funcs = _TypeEqualityDict(self)
278-        self.addTypeEqualityFunc(dict, 'assertDictEqual')
279-        self.addTypeEqualityFunc(list, 'assertListEqual')
280-        self.addTypeEqualityFunc(tuple, 'assertTupleEqual')
281-        self.addTypeEqualityFunc(set, 'assertSetEqual')
282-        self.addTypeEqualityFunc(frozenset, 'assertSetEqual')
283-        self.addTypeEqualityFunc(unicode, 'assertMultiLineEqual')
284+        self._type_equality_funcs = {}
285+        self.addTypeEqualityFunc(dict, self.assertDictEqual)
286+        self.addTypeEqualityFunc(list, self.assertListEqual)
287+        self.addTypeEqualityFunc(tuple, self.assertTupleEqual)
288+        self.addTypeEqualityFunc(set, self.assertSetEqual)
289+        self.addTypeEqualityFunc(frozenset, self.assertSetEqual)
290+        self.addTypeEqualityFunc(unicode, self.assertMultiLineEqual)
291 
292     def addTypeEqualityFunc(self, typeobj, function):
293         """Add a type specific assertEqual style function to compare a type.
294@@ -243,6 +228,11 @@
295 
296     def setUp(self):
297         "Hook method for setting up the test fixture before exercising it."
298+        pass
299+
300+    def tearDown(self):
301+        "Hook method for deconstructing the test fixture after testing it."
302+        pass
303 
304     @classmethod
305     def setUpClass(cls):
306@@ -252,9 +242,6 @@
307     def tearDownClass(cls):
308         "Hook method for deconstructing the class fixture after running all tests in the class."
309 
310-    def tearDown(self):
311-        "Hook method for deconstructing the test fixture after testing it."
312-
313     def countTestCases(self):
314         return 1
315 
316@@ -299,8 +286,8 @@
317         if addSkip is not None:
318             addSkip(self, reason)
319         else:
320-            warnings.warn("Use of a TestResult without an addSkip method is deprecated",
321-                          DeprecationWarning, 2)
322+            warnings.warn("TestResult has no addSkip method, skips not reported",
323+                          RuntimeWarning, 2)
324             result.addSuccess(self)
325 
326     def run(self, result=None):
327@@ -315,7 +302,6 @@
328         result.startTest(self)
329 
330         testMethod = getattr(self, self._testMethodName)
331-
332         if (getattr(self.__class__, "__unittest_skip__", False) or
333             getattr(testMethod, "__unittest_skip__", False)):
334             # If the class or method was skipped.
335@@ -330,41 +316,47 @@
336             success = False
337             try:
338                 self.setUp()
339-            except SkipTest, e:
340+            except SkipTest as e:
341                 self._addSkip(result, str(e))
342-            except Exception:
343+            except KeyboardInterrupt:
344+                raise
345+            except:
346                 result.addError(self, sys.exc_info())
347             else:
348                 try:
349                     testMethod()
350+                except KeyboardInterrupt:
351+                    raise
352                 except self.failureException:
353                     result.addFailure(self, sys.exc_info())
354-                except _ExpectedFailure, e:
355+                except _ExpectedFailure as e:
356                     addExpectedFailure = getattr(result, 'addExpectedFailure', None)
357                     if addExpectedFailure is not None:
358                         addExpectedFailure(self, e.exc_info)
359                     else:
360-                        warnings.warn("Use of a TestResult without an addExpectedFailure method is deprecated",
361-                                      DeprecationWarning)
362+                        warnings.warn("TestResult has no addExpectedFailure method, reporting as passes",
363+                                      RuntimeWarning)
364                         result.addSuccess(self)
365                 except _UnexpectedSuccess:
366                     addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess', None)
367                     if addUnexpectedSuccess is not None:
368                         addUnexpectedSuccess(self)
369                     else:
370-                        warnings.warn("Use of a TestResult without an addUnexpectedSuccess method is deprecated",
371-                                      DeprecationWarning)
372+                        warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failures",
373+                                      RuntimeWarning)
374                         result.addFailure(self, sys.exc_info())
375-                except SkipTest, e:
376+                except SkipTest as e:
377                     self._addSkip(result, str(e))
378-                except Exception:
379+                except:
380                     result.addError(self, sys.exc_info())
381                 else:
382                     success = True
383 
384                 try:
385                     self.tearDown()
386-                except Exception:
387+                except KeyboardInterrupt:
388+                    raise
389+                except:
390                     result.addError(self, sys.exc_info())
391                     success = False
392 
393@@ -388,7 +380,9 @@
394             function, args, kwargs = self._cleanups.pop(-1)
395             try:
396                 function(*args, **kwargs)
397-            except Exception:
398+            except KeyboardInterrupt:
399+                raise
400+            except:
401                 ok = False
402                 result.addError(self, sys.exc_info())
403         return ok
404@@ -414,15 +408,15 @@
405         raise self.failureException(msg)
406 
407     def assertFalse(self, expr, msg=None):
408-        "Fail the test if the expression is true."
409+        """Check that the expression is false."""
410         if expr:
411-            msg = self._formatMessage(msg, "%s is not False" % safe_repr(expr))
412+            msg = self._formatMessage(msg, "%s is not false" % safe_repr(expr))
413             raise self.failureException(msg)
414 
415     def assertTrue(self, expr, msg=None):
416-        """Fail the test unless the expression is true."""
417+        """Check that the expression is true."""
418         if not expr:
419-            msg = self._formatMessage(msg, "%s is not True" % safe_repr(expr))
420+            msg = self._formatMessage(msg, "%s is not true" % safe_repr(expr))
421             raise self.failureException(msg)
422 
423     def _formatMessage(self, msg, standardMsg):
424@@ -440,9 +434,11 @@
425         if msg is None:
426             return standardMsg
427         try:
428+            # don't switch to '{}' formatting in Python 2.X
429+            # it changes the way unicode input is handled
430             return '%s : %s' % (standardMsg, msg)
431         except UnicodeDecodeError:
432-            return '%s : %s' % (safe_str(standardMsg), safe_str(msg))
433+            return  '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
434 
435 
436     def assertRaises(self, excClass, callableObj=None, *args, **kwargs):
437@@ -468,18 +464,11 @@
438                the_exception = cm.exception
439                self.assertEqual(the_exception.error_code, 3)
440         """
441+        context = _AssertRaisesContext(excClass, self)
442         if callableObj is None:
443-            return _AssertRaisesContext(excClass, self)
444-        try:
445+            return context
446+        with context:
447             callableObj(*args, **kwargs)
448-        except excClass:
449-            return
450-
451-        if hasattr(excClass,'__name__'):
452-            excName = excClass.__name__
453-        else:
454-            excName = str(excClass)
455-        raise self.failureException("%s not raised" % excName)
456 
457     def _getAssertEqualityFunc(self, first, second):
458         """Get a detailed comparison function for the types of the two args.
459@@ -528,6 +517,7 @@
460                                                            safe_repr(second)))
461             raise self.failureException(msg)
462 
463+
464     def assertAlmostEqual(self, first, second, places=None, msg=None, delta=None):
465         """Fail if the two objects are unequal as determined by their
466            difference rounded to the given number of decimal places
467@@ -613,7 +603,7 @@
468     def _deprecate(original_func):
469         def deprecated_func(*args, **kwargs):
470             warnings.warn(
471-                ('Please use %s instead.' % original_func.__name__),
472+                'Please use {0} instead.'.format(original_func.__name__),
473                 PendingDeprecationWarning, 2)
474             return original_func(*args, **kwargs)
475         return deprecated_func
476@@ -626,8 +616,7 @@
477     failUnlessRaises = _deprecate(assertRaises)
478     failIf = _deprecate(assertFalse)
479 
480-    def assertSequenceEqual(self, seq1, seq2,
481-                            msg=None, seq_type=None, max_diff=80*8):
482+    def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
483         """An equality assertion for ordered sequences (like lists and tuples).
484 
485         For the purposes of this function, a valid ordered sequence type is one
486@@ -640,7 +629,6 @@
487                     datatype should be enforced.
488             msg: Optional message to use on failure instead of a list of
489                     differences.
490-            max_diff: Maximum size off the diff, larger diffs are not shown
491         """
492         if seq_type is not None:
493             seq_type_name = seq_type.__name__
494@@ -671,8 +659,8 @@
495             if seq1 == seq2:
496                 return
497 
498-            seq1_repr = repr(seq1)
499-            seq2_repr = repr(seq2)
500+            seq1_repr = safe_repr(seq1)
501+            seq2_repr = safe_repr(seq2)
502             if len(seq1_repr) > 30:
503                 seq1_repr = seq1_repr[:30] + '...'
504             if len(seq2_repr) > 30:
505@@ -727,7 +715,6 @@
506         diffMsg = '\n' + '\n'.join(
507             difflib.ndiff(pprint.pformat(seq1).splitlines(),
508                           pprint.pformat(seq2).splitlines()))
509-
510         standardMsg = self._truncateMessage(standardMsg, diffMsg)
511         msg = self._formatMessage(msg, standardMsg)
512         self.fail(msg)
513@@ -770,9 +757,9 @@
514             msg: Optional message to use on failure instead of a list of
515                     differences.
516 
517-        assertSetEqual uses ducktyping to support
518-        different types of sets, and is optimized for sets specifically
519-        (parameters must support a difference method).
520+        assertSetEqual uses ducktyping to support different types of sets, and
521+        is optimized for sets specifically (parameters must support a
522+        difference method).
523         """
524         try:
525             difference1 = set1.difference(set2)
526@@ -821,7 +808,8 @@
527     def assertIs(self, expr1, expr2, msg=None):
528         """Just like self.assertTrue(a is b), but with a nicer default message."""
529         if expr1 is not expr2:
530-            standardMsg = '%s is not %s' % (safe_repr(expr1), safe_repr(expr2))
531+            standardMsg = '%s is not %s' % (safe_repr(expr1),
532+                                             safe_repr(expr2))
533             self.fail(self._formatMessage(msg, standardMsg))
534 
535     def assertIsNot(self, expr1, expr2, msg=None):
536@@ -831,8 +819,8 @@
537             self.fail(self._formatMessage(msg, standardMsg))
538 
539     def assertDictEqual(self, d1, d2, msg=None):
540-        self.assertTrue(isinstance(d1, dict), 'First argument is not a dictionary')
541-        self.assertTrue(isinstance(d2, dict), 'Second argument is not a dictionary')
542+        self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
543+        self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')
544 
545         if d1 != d2:
546             standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True))
547@@ -870,54 +858,64 @@
548 
549     def assertItemsEqual(self, expected_seq, actual_seq, msg=None):
550         """An unordered sequence specific comparison. It asserts that
551-        expected_seq and actual_seq contain the same elements. It is
552-        the equivalent of::
553+        actual_seq and expected_seq have the same element counts.
554+        Equivalent to::
555 
556-            self.assertEqual(sorted(expected_seq), sorted(actual_seq))
557-
558-        Raises with an error message listing which elements of expected_seq
559-        are missing from actual_seq and vice versa if any.
560+            self.assertEqual(Counter(iter(actual_seq)),
561+                             Counter(iter(expected_seq)))
562 
563         Asserts that each element has the same count in both sequences.
564         Example:
565             - [0, 1, 1] and [1, 0, 1] compare equal.
566             - [0, 0, 1] and [0, 1] compare unequal.
567         """
568+        first_seq, second_seq = list(actual_seq), list(expected_seq)
569+        with warnings.catch_warnings():
570+            if sys.py3kwarning:
571+                # Silence Py3k warning raised during the sorting
572+                for _msg in ["(code|dict|type) inequality comparisons",
573+                             "builtin_function_or_method order comparisons",
574+                             "comparing unequal types"]:
575+                    warnings.filterwarnings("ignore", _msg, DeprecationWarning)
576         try:
577-            expected = sorted(expected_seq)
578-            actual = sorted(actual_seq)
579+                first = collections.Counter(first_seq)
580+                second = collections.Counter(second_seq)
581         except TypeError:
582-            # Unsortable items (example: set(), complex(), ...)
583-            expected = list(expected_seq)
584-            actual = list(actual_seq)
585-            missing, unexpected = unorderable_list_difference(
586-                expected, actual, ignore_duplicate=False
587-            )
588+                # Handle case with unhashable elements
589+                differences = _count_diff_all_purpose(first_seq, second_seq)
590         else:
591-            return self.assertSequenceEqual(expected, actual, msg=msg)
592+                if first == second:
593+                    return
594+                differences = _count_diff_hashable(first_seq, second_seq)
595 
596-        errors = []
597-        if missing:
598-            errors.append('Expected, but missing:\n    %s' %
599-                           safe_repr(missing))
600-        if unexpected:
601-            errors.append('Unexpected, but present:\n    %s' %
602-                           safe_repr(unexpected))
603-        if errors:
604-            standardMsg = '\n'.join(errors)
605-            self.fail(self._formatMessage(msg, standardMsg))
606+        if differences:
607+            standardMsg = 'Element counts were not equal:\n'
608+            lines = ['First has %d, Second has %d:  %r' % diff for diff in differences]
609+            diffMsg = '\n'.join(lines)
610+            standardMsg = self._truncateMessage(standardMsg, diffMsg)
611+            msg = self._formatMessage(msg, standardMsg)
612+            self.fail(msg)
613 
614     def assertMultiLineEqual(self, first, second, msg=None):
615         """Assert that two multi-line strings are equal."""
616-        self.assertTrue(isinstance(first, basestring), (
617-                'First argument is not a string'))
618-        self.assertTrue(isinstance(second, basestring), (
619-                'Second argument is not a string'))
620+        self.assertIsInstance(first, basestring,
621+                'First argument is not a string')
622+        self.assertIsInstance(second, basestring,
623+                'Second argument is not a string')
624 
625         if first != second:
626-            standardMsg = '%s != %s' % (safe_repr(first, True), safe_repr(second, True))
627-            diff = '\n' + ''.join(difflib.ndiff(first.splitlines(True),
628-                                                       second.splitlines(True)))
629+            # don't use difflib if the strings are too long
630+            if (len(first) > self._diffThreshold or
631+                len(second) > self._diffThreshold):
632+                self._baseAssertEqual(first, second, msg)
633+            firstlines = first.splitlines(True)
634+            secondlines = second.splitlines(True)
635+            if len(firstlines) == 1 and first.strip('\r\n') == first:
636+                firstlines = [first + '\n']
637+                secondlines = [second + '\n']
638+            standardMsg = '%s != %s' % (safe_repr(first, True),
639+                                        safe_repr(second, True))
640+            diff = '\n' + ''.join(difflib.ndiff(firstlines, secondlines))
641             standardMsg = self._truncateMessage(standardMsg, diff)
642             self.fail(self._formatMessage(msg, standardMsg))
643 
644@@ -982,22 +980,11 @@
645             args: Extra args.
646             kwargs: Extra kwargs.
647         """
648+        context = _AssertRaisesContext(expected_exception, self, expected_regexp)
649         if callable_obj is None:
650-            return _AssertRaisesContext(expected_exception, self, expected_regexp)
651-        try:
652+            return context
653+        with context:
654             callable_obj(*args, **kwargs)
655-        except expected_exception, exc_value:
656-            if isinstance(expected_regexp, basestring):
657-                expected_regexp = re.compile(expected_regexp)
658-            if not expected_regexp.search(str(exc_value)):
659-                raise self.failureException('"%s" does not match "%s"' %
660-                         (expected_regexp.pattern, str(exc_value)))
661-        else:
662-            if hasattr(expected_exception, '__name__'):
663-                excName = expected_exception.__name__
664-            else:
665-                excName = str(expected_exception)
666-            raise self.failureException("%s not raised" % excName)
667 
668     def assertRegexpMatches(self, text, expected_regexp, msg=None):
669         """Fail the test unless the text matches the regular expression."""
670@@ -1021,6 +1008,7 @@
671                                                text)
672             raise self.failureException(msg)
673 
674+
675 class FunctionTestCase(TestCase):
676     """A test case that wraps a test function.
677 
678@@ -1072,7 +1060,7 @@
679                             self._testFunc.__name__)
680 
681     def __repr__(self):
682-        return "<%s testFunc=%s>" % (strclass(self.__class__),
683+        return "<%s tec=%s>" % (strclass(self.__class__),
684                                      self._testFunc)
685 
686     def shortDescription(self):
687diff -u -Naur -x .svn -x .DS_Store -x test -x '*.pyc' -w django/utils/unittest/collector.py /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/collector.py
688--- django/utils/unittest/collector.py  2011-05-04 23:17:48.000000000 +0200
689+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/collector.py 1970-01-01 01:00:00.000000000 +0100
690@@ -1,9 +0,0 @@
691-import os
692-import sys
693-from django.utils.unittest.loader import defaultTestLoader
694-
695-def collector():
696-    # import __main__ triggers code re-execution
697-    __main__ = sys.modules['__main__']
698-    setupDir = os.path.abspath(os.path.dirname(__main__.__file__))
699-    return defaultTestLoader.discover(setupDir)
700diff -u -Naur -x .svn -x .DS_Store -x test -x '*.pyc' -w django/utils/unittest/compatibility.py /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/compatibility.py
701--- django/utils/unittest/compatibility.py      2011-07-10 20:15:49.000000000 +0200
702+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/compatibility.py     1970-01-01 01:00:00.000000000 +0100
703@@ -1,64 +0,0 @@
704-import os
705-import sys
706-
707-try:
708-    from functools import wraps
709-except ImportError:
710-    # only needed for Python 2.4
711-    def wraps(_):
712-        def _wraps(func):
713-            return func
714-        return _wraps
715-
716-__unittest = True
717-
718-def _relpath_nt(path, start=os.path.curdir):
719-    """Return a relative version of a path"""
720-
721-    if not path:
722-        raise ValueError("no path specified")
723-    start_list = os.path.abspath(start).split(os.path.sep)
724-    path_list = os.path.abspath(path).split(os.path.sep)
725-    if start_list[0].lower() != path_list[0].lower():
726-        unc_path, rest = os.path.splitunc(path)
727-        unc_start, rest = os.path.splitunc(start)
728-        if bool(unc_path) ^ bool(unc_start):
729-            raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
730-                                                                % (path, start))
731-        else:
732-            raise ValueError("path is on drive %s, start on drive %s"
733-                                                % (path_list[0], start_list[0]))
734-    # Work out how much of the filepath is shared by start and path.
735-    for i in range(min(len(start_list), len(path_list))):
736-        if start_list[i].lower() != path_list[i].lower():
737-            break
738-    else:
739-        i += 1
740-
741-    rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
742-    if not rel_list:
743-        return os.path.curdir
744-    return os.path.join(*rel_list)
745-
746-# default to posixpath definition
747-def _relpath_posix(path, start=os.path.curdir):
748-    """Return a relative version of a path"""
749-
750-    if not path:
751-        raise ValueError("no path specified")
752-
753-    start_list = os.path.abspath(start).split(os.path.sep)
754-    path_list = os.path.abspath(path).split(os.path.sep)
755-
756-    # Work out how much of the filepath is shared by start and path.
757-    i = len(os.path.commonprefix([start_list, path_list]))
758-
759-    rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
760-    if not rel_list:
761-        return os.path.curdir
762-    return os.path.join(*rel_list)
763-
764-if os.path is sys.modules.get('ntpath'):
765-    relpath = _relpath_nt
766-else:
767-    relpath = _relpath_posix
768diff -u -Naur -x .svn -x .DS_Store -x test -x '*.pyc' -w django/utils/unittest/loader.py /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/loader.py
769--- django/utils/unittest/loader.py     2011-05-04 23:17:48.000000000 +0200
770+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/loader.py    2011-06-11 15:50:36.000000000 +0200
771@@ -5,30 +5,14 @@
772 import sys
773 import traceback
774 import types
775-import unittest
776 
777+from functools import cmp_to_key as _CmpToKey
778 from fnmatch import fnmatch
779 
780-from django.utils.unittest import case, suite
781-
782-try:
783-    from os.path import relpath
784-except ImportError:
785-    from django.utils.unittest.compatibility import relpath
786+from . import case, suite
787 
788 __unittest = True
789 
790-
791-def _CmpToKey(mycmp):
792-    'Convert a cmp= function into a key= function'
793-    class K(object):
794-        def __init__(self, obj):
795-            self.obj = obj
796-        def __lt__(self, other):
797-            return mycmp(self.obj, other.obj) == -1
798-    return K
799-
800-
801 # what about .pyc or .pyo (etc)
802 # we would need to avoid loading the same tests multiple times
803 # from '.py', '.pyc' *and* '.pyo'
804@@ -36,11 +20,7 @@
805 
806 
807 def _make_failed_import_test(name, suiteClass):
808-    message = 'Failed to import test module: %s' % name
809-    if hasattr(traceback, 'format_exc'):
810-        # Python 2.3 compatibility
811-        # format_exc returns two frames of discover.py as well
812-        message += '\n%s' % traceback.format_exc()
813+    message = 'Failed to import test module: %s\n%s' % (name, traceback.format_exc())
814     return _make_failed_test('ModuleImportFailure', name, ImportError(message),
815                              suiteClass)
816 
817@@ -55,7 +35,7 @@
818     return suiteClass((TestClass(methodname),))
819 
820 
821-class TestLoader(unittest.TestLoader):
822+class TestLoader(object):
823     """
824     This class is responsible for loading tests according to various criteria
825     and returning them wrapped in a TestSuite
826@@ -68,7 +48,7 @@
827     def loadTestsFromTestCase(self, testCaseClass):
828         """Return a suite of all tests cases contained in testCaseClass"""
829         if issubclass(testCaseClass, suite.TestSuite):
830-            raise TypeError("Test cases should not be derived from TestSuite."
831+            raise TypeError("Test cases should not be derived from TestSuite." \
832                             " Maybe you meant to derive from TestCase?")
833         testCaseNames = self.getTestCaseNames(testCaseClass)
834         if not testCaseNames and hasattr(testCaseClass, 'runTest'):
835@@ -81,7 +61,7 @@
836         tests = []
837         for name in dir(module):
838             obj = getattr(module, name)
839-            if isinstance(obj, type) and issubclass(obj, unittest.TestCase):
840+            if isinstance(obj, type) and issubclass(obj, case.TestCase):
841                 tests.append(self.loadTestsFromTestCase(obj))
842 
843         load_tests = getattr(module, 'load_tests', None)
844@@ -121,19 +101,19 @@
845 
846         if isinstance(obj, types.ModuleType):
847             return self.loadTestsFromModule(obj)
848-        elif isinstance(obj, type) and issubclass(obj, unittest.TestCase):
849+        elif isinstance(obj, type) and issubclass(obj, case.TestCase):
850             return self.loadTestsFromTestCase(obj)
851         elif (isinstance(obj, types.UnboundMethodType) and
852               isinstance(parent, type) and
853               issubclass(parent, case.TestCase)):
854             return self.suiteClass([parent(obj.__name__)])
855-        elif isinstance(obj, unittest.TestSuite):
856+        elif isinstance(obj, suite.TestSuite):
857             return obj
858         elif hasattr(obj, '__call__'):
859             test = obj()
860-            if isinstance(test, unittest.TestSuite):
861+            if isinstance(test, suite.TestSuite):
862                 return test
863-            elif isinstance(test, unittest.TestCase):
864+            elif isinstance(test, case.TestCase):
865                 return self.suiteClass([test])
866             else:
867                 raise TypeError("calling %s returned %s, not a test" %
868@@ -215,7 +195,7 @@
869                 top_part = start_dir.split('.')[0]
870                 start_dir = os.path.abspath(os.path.dirname((the_module.__file__)))
871                 if set_implicit_top:
872-                    self._top_level_dir = os.path.abspath(os.path.dirname(os.path.dirname(sys.modules[top_part].__file__)))
873+                    self._top_level_dir = self._get_directory_containing_module(top_part)
874                     sys.path.remove(top_level_dir)
875 
876         if is_not_importable:
877@@ -224,10 +204,22 @@
878         tests = list(self._find_tests(start_dir, pattern))
879         return self.suiteClass(tests)
880 
881+    def _get_directory_containing_module(self, module_name):
882+        module = sys.modules[module_name]
883+        full_path = os.path.abspath(module.__file__)
884+
885+        if os.path.basename(full_path).lower().startswith('__init__.py'):
886+            return os.path.dirname(os.path.dirname(full_path))
887+        else:
888+            # here we have been given a module rather than a package - so
889+            # all we can do is search the *same* directory the module is in
890+            # should an exception be raised instead
891+            return os.path.dirname(full_path)
892+
893     def _get_name_from_path(self, path):
894         path = os.path.splitext(os.path.normpath(path))[0]
895 
896-        _relpath = relpath(path, self._top_level_dir)
897+        _relpath = os.path.relpath(path, self._top_level_dir)
898         assert not os.path.isabs(_relpath), "Path must be within the project"
899         assert not _relpath.startswith('..'), "Path must be within the project"
900 
901diff -u -Naur -x .svn -x .DS_Store -x test -x '*.pyc' -w django/utils/unittest/main.py /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/main.py
902--- django/utils/unittest/main.py       2011-05-04 23:17:48.000000000 +0200
903+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/main.py      2011-06-11 15:50:36.000000000 +0200
904@@ -4,11 +4,8 @@
905 import os
906 import types
907 
908-from django.utils.unittest import loader, runner
909-try:
910-    from django.utils.unittest.signals import installHandler
911-except ImportError:
912-    installHandler = None
913+from . import loader, runner
914+from .signals import installHandler
915 
916 __unittest = True
917 
918@@ -26,9 +23,8 @@
919 %(failfast)s%(catchbreak)s%(buffer)s
920 Examples:
921   %(progName)s test_module                       - run tests from test_module
922-  %(progName)s test_module.TestClass             - run tests from
923-                                                   test_module.TestClass
924-  %(progName)s test_module.TestClass.test_method - run specified test method
925+  %(progName)s module.TestClass          - run tests from module.TestClass
926+  %(progName)s module.Class.test_method  - run specified test method
927 
928 [tests] can be a list of any number of test modules, classes and test
929 methods.
930@@ -63,6 +59,7 @@
931 """
932 
933 
934+
935 class TestProgram(object):
936     """A command-line program that runs a set of tests; this is primarily
937        for making test modules conveniently executable.
938@@ -72,10 +69,10 @@
939     # defaults for testing
940     failfast = catchbreak = buffer = progName = None
941 
942-    def __init__(self, module='__main__', defaultTest=None,
943-                 argv=None, testRunner=None,
944-                 testLoader=loader.defaultTestLoader, exit=True,
945-                 verbosity=1, failfast=None, catchbreak=None, buffer=None):
946+    def __init__(self, module='__main__', defaultTest=None, argv=None,
947+                    testRunner=None, testLoader=loader.defaultTestLoader,
948+                    exit=True, verbosity=1, failfast=None, catchbreak=None,
949+                    buffer=None):
950         if isinstance(module, basestring):
951             self.module = __import__(module)
952             for part in module.split('.')[1:]:
953@@ -86,9 +83,9 @@
954             argv = sys.argv
955 
956         self.exit = exit
957-        self.verbosity = verbosity
958         self.failfast = failfast
959         self.catchbreak = catchbreak
960+        self.verbosity = verbosity
961         self.buffer = buffer
962         self.defaultTest = defaultTest
963         self.testRunner = testRunner
964@@ -104,7 +101,7 @@
965                  'buffer': ''}
966         if self.failfast != False:
967             usage['failfast'] = FAILFAST
968-        if self.catchbreak != False and installHandler is not None:
969+        if self.catchbreak != False:
970             usage['catchbreak'] = CATCHBREAK
971         if self.buffer != False:
972             usage['buffer'] = BUFFEROUTPUT
973@@ -132,7 +129,7 @@
974                         self.failfast = True
975                     # Should this raise an exception if -f is not valid?
976                 if opt in ('-c','--catch'):
977-                    if self.catchbreak is None and installHandler is not None:
978+                    if self.catchbreak is None:
979                         self.catchbreak = True
980                     # Should this raise an exception if -c is not valid?
981                 if opt in ('-b','--buffer'):
982@@ -172,7 +169,7 @@
983             parser.add_option('-f', '--failfast', dest='failfast', default=False,
984                               help='Stop on first fail or error',
985                               action='store_true')
986-        if self.catchbreak != False and installHandler is not None:
987+        if self.catchbreak != False:
988             parser.add_option('-c', '--catch', dest='catchbreak', default=False,
989                               help='Catch ctrl-C and display results so far',
990                               action='store_true')
991@@ -198,7 +195,7 @@
992         # if they weren't set explicitly in the constructor
993         if self.failfast is None:
994             self.failfast = options.failfast
995-        if self.catchbreak is None and installHandler is not None:
996+        if self.catchbreak is None:
997             self.catchbreak = options.catchbreak
998         if self.buffer is None:
999             self.buffer = options.buffer
1000@@ -234,8 +231,3 @@
1001             sys.exit(not self.result.wasSuccessful())
1002 
1003 main = TestProgram
1004-
1005-def main_():
1006-    TestProgram.USAGE = USAGE_AS_MAIN
1007-    main(module=None)
1008-
1009diff -u -Naur -x .svn -x .DS_Store -x test -x '*.pyc' -w django/utils/unittest/result.py /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/result.py
1010--- django/utils/unittest/result.py     2011-07-10 20:15:49.000000000 +0200
1011+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/result.py    2011-06-11 15:50:36.000000000 +0200
1012@@ -1,13 +1,13 @@
1013 """Test result object"""
1014 
1015+import os
1016 import sys
1017 import traceback
1018-import unittest
1019 
1020 from StringIO import StringIO
1021 
1022-from django.utils.unittest import util
1023-from django.utils.unittest.compatibility import wraps
1024+from . import util
1025+from functools import wraps
1026 
1027 __unittest = True
1028 
1029@@ -19,11 +19,11 @@
1030         return method(self, *args, **kw)
1031     return inner
1032 
1033-
1034 STDOUT_LINE = '\nStdout:\n%s'
1035 STDERR_LINE = '\nStderr:\n%s'
1036 
1037-class TestResult(unittest.TestResult):
1038+
1039+class TestResult(object):
1040     """Holder for test result information.
1041 
1042     Test results are automatically managed by the TestCase and TestSuite
1043@@ -35,9 +35,9 @@
1044     formatted traceback of the error that occurred.
1045     """
1046     _previousTestClass = None
1047+    _testRunEntered = False
1048     _moduleSetUpFailed = False
1049-
1050-    def __init__(self):
1051+    def __init__(self, stream=None, descriptions=None, verbosity=None):
1052         self.failfast = False
1053         self.failures = []
1054         self.errors = []
1055@@ -53,10 +53,16 @@
1056         self._original_stderr = sys.stderr
1057         self._mirrorOutput = False
1058 
1059+    def printErrors(self):
1060+        "Called by TestRunner after test run"
1061+
1062     def startTest(self, test):
1063         "Called when the given test is about to be run"
1064         self.testsRun += 1
1065         self._mirrorOutput = False
1066+        self._setupStdout()
1067+
1068+    def _setupStdout(self):
1069         if self.buffer:
1070             if self._stderr_buffer is None:
1071                 self._stderr_buffer = StringIO()
1072@@ -72,6 +78,10 @@
1073 
1074     def stopTest(self, test):
1075         """Called when the given test has been run"""
1076+        self._restoreStdout()
1077+        self._mirrorOutput = False
1078+
1079+    def _restoreStdout(self):
1080         if self.buffer:
1081             if self._mirrorOutput:
1082                 output = sys.stdout.getvalue()
1083@@ -91,8 +101,6 @@
1084             self._stdout_buffer.truncate()
1085             self._stderr_buffer.seek(0)
1086             self._stderr_buffer.truncate()
1087-        self._mirrorOutput = False
1088-
1089 
1090     def stopTestRun(self):
1091         """Called once after all tests are executed.
1092@@ -135,7 +143,7 @@
1093 
1094     def wasSuccessful(self):
1095         "Tells whether or not this result was a success"
1096-        return (len(self.failures) + len(self.errors) == 0)
1097+        return len(self.failures) == len(self.errors) == 0
1098 
1099     def stop(self):
1100         "Indicates that the tests should be aborted"
1101@@ -147,6 +155,7 @@
1102         # Skip test runner traceback levels
1103         while tb and self._is_relevant_tb_level(tb):
1104             tb = tb.tb_next
1105+
1106         if exctype is test.failureException:
1107             # Skip assert*() traceback levels
1108             length = self._count_relevant_tb_levels(tb)
1109@@ -167,6 +176,7 @@
1110                 msgLines.append(STDERR_LINE % error)
1111         return ''.join(msgLines)
1112 
1113+
1114     def _is_relevant_tb_level(self, tb):
1115         return '__unittest' in tb.tb_frame.f_globals
1116 
1117@@ -178,6 +188,6 @@
1118         return length
1119 
1120     def __repr__(self):
1121-        return "<%s run=%i errors=%i failures=%i>" % \
1122+        return ("<%s run=%i errors=%i failures=%i>" %
1123                (util.strclass(self.__class__), self.testsRun, len(self.errors),
1124-                len(self.failures))
1125+                len(self.failures)))
1126diff -u -Naur -x .svn -x .DS_Store -x test -x '*.pyc' -w django/utils/unittest/runner.py /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/runner.py
1127--- django/utils/unittest/runner.py     2011-05-04 23:17:48.000000000 +0200
1128+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/runner.py    2011-06-11 15:50:36.000000000 +0200
1129@@ -2,15 +2,9 @@
1130 
1131 import sys
1132 import time
1133-import unittest
1134 
1135-from django.utils.unittest import result
1136-
1137-try:
1138-    from django.utils.unittest.signals import registerResult
1139-except ImportError:
1140-    def registerResult(_):
1141-        pass
1142+from . import result
1143+from .signals import registerResult
1144 
1145 __unittest = True
1146 
1147@@ -87,7 +81,7 @@
1148     def addSkip(self, test, reason):
1149         super(TextTestResult, self).addSkip(test, reason)
1150         if self.showAll:
1151-            self.stream.writeln("skipped %r" % (reason,))
1152+            self.stream.writeln("skipped {0!r}".format(reason))
1153         elif self.dots:
1154             self.stream.write("s")
1155             self.stream.flush()
1156@@ -121,12 +115,8 @@
1157             self.stream.writeln(self.separator2)
1158             self.stream.writeln("%s" % err)
1159 
1160-    def stopTestRun(self):
1161-        super(TextTestResult, self).stopTestRun()
1162-        self.printErrors()
1163-
1164 
1165-class TextTestRunner(unittest.TextTestRunner):
1166+class TextTestRunner(object):
1167     """A test runner class that displays results in textual form.
1168 
1169     It prints out the names of tests as they are run, errors as they
1170@@ -150,10 +140,9 @@
1171     def run(self, test):
1172         "Run the given test case or test suite."
1173         result = self._makeResult()
1174+        registerResult(result)
1175         result.failfast = self.failfast
1176         result.buffer = self.buffer
1177-        registerResult(result)
1178-
1179         startTime = time.time()
1180         startTestRun = getattr(result, 'startTestRun', None)
1181         if startTestRun is not None:
1182@@ -164,10 +153,9 @@
1183             stopTestRun = getattr(result, 'stopTestRun', None)
1184             if stopTestRun is not None:
1185                 stopTestRun()
1186-            else:
1187-                result.printErrors()
1188         stopTime = time.time()
1189         timeTaken = stopTime - startTime
1190+        result.printErrors()
1191         if hasattr(result, 'separator2'):
1192             self.stream.writeln(result.separator2)
1193         run = result.testsRun
1194@@ -180,9 +168,11 @@
1195             results = map(len, (result.expectedFailures,
1196                                 result.unexpectedSuccesses,
1197                                 result.skipped))
1198-            expectedFails, unexpectedSuccesses, skipped = results
1199         except AttributeError:
1200             pass
1201+        else:
1202+            expectedFails, unexpectedSuccesses, skipped = results
1203+
1204         infos = []
1205         if not result.wasSuccessful():
1206             self.stream.write("FAILED")
1207diff -u -Naur -x .svn -x .DS_Store -x test -x '*.pyc' -w django/utils/unittest/signals.py /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/signals.py
1208--- django/utils/unittest/signals.py    2011-07-10 20:15:49.000000000 +0200
1209+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/signals.py   2011-06-11 15:50:36.000000000 +0200
1210@@ -1,7 +1,7 @@
1211 import signal
1212 import weakref
1213 
1214-from django.utils.unittest.compatibility import wraps
1215+from functools import wraps
1216 
1217 __unittest = True
1218 
1219diff -u -Naur -x .svn -x .DS_Store -x test -x '*.pyc' -w django/utils/unittest/suite.py /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/suite.py
1220--- django/utils/unittest/suite.py      2011-05-04 23:17:48.000000000 +0200
1221+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/suite.py     2011-06-11 15:50:36.000000000 +0200
1222@@ -1,13 +1,19 @@
1223 """TestSuite"""
1224 
1225 import sys
1226-import unittest
1227-from django.utils.unittest import case, util
1228+
1229+from . import case
1230+from . import util
1231 
1232 __unittest = True
1233 
1234 
1235-class BaseTestSuite(unittest.TestSuite):
1236+def _call_if_exists(parent, attr):
1237+    func = getattr(parent, attr, lambda: None)
1238+    func()
1239+
1240+
1241+class BaseTestSuite(object):
1242     """A simple test suite that doesn't provide class or module shared fixtures.
1243     """
1244     def __init__(self, tests=()):
1245@@ -40,7 +46,7 @@
1246     def addTest(self, test):
1247         # sanity checks
1248         if not hasattr(test, '__call__'):
1249-            raise TypeError("%r is not callable" % (repr(test),))
1250+            raise TypeError("{} is not callable".format(repr(test)))
1251         if isinstance(test, type) and issubclass(test,
1252                                                  (case.TestCase, TestSuite)):
1253             raise TypeError("TestCases and TestSuites must be instantiated "
1254@@ -79,23 +85,11 @@
1255     subclassing, do not forget to call the base class constructor.
1256     """
1257 
1258+    def run(self, result, debug=False):
1259+        topLevel = False
1260+        if getattr(result, '_testRunEntered', False) is False:
1261+            result._testRunEntered = topLevel = True
1262 
1263-    def run(self, result):
1264-        self._wrapped_run(result)
1265-        self._tearDownPreviousClass(None, result)
1266-        self._handleModuleTearDown(result)
1267-        return result
1268-
1269-    def debug(self):
1270-        """Run the tests without collecting errors in a TestResult"""
1271-        debug = _DebugResult()
1272-        self._wrapped_run(debug, True)
1273-        self._tearDownPreviousClass(None, debug)
1274-        self._handleModuleTearDown(debug)
1275-
1276-    ################################
1277-    # private methods
1278-    def _wrapped_run(self, result, debug=False):
1279         for test in self:
1280             if result.shouldStop:
1281                 break
1282@@ -110,13 +104,24 @@
1283                     getattr(result, '_moduleSetUpFailed', False)):
1284                     continue
1285 
1286-            if hasattr(test, '_wrapped_run'):
1287-                test._wrapped_run(result, debug)
1288-            elif not debug:
1289+            if not debug:
1290                 test(result)
1291             else:
1292                 test.debug()
1293 
1294+        if topLevel:
1295+            self._tearDownPreviousClass(None, result)
1296+            self._handleModuleTearDown(result)
1297+            result._testRunEntered = False
1298+        return result
1299+
1300+    def debug(self):
1301+        """Run the tests without collecting errors in a TestResult"""
1302+        debug = _DebugResult()
1303+        self.run(debug, True)
1304+
1305+    ################################
1306+
1307     def _handleClassSetUp(self, test, result):
1308         previousClass = getattr(result, '_previousTestClass', None)
1309         currentClass = test.__class__
1310@@ -136,15 +141,18 @@
1311 
1312         setUpClass = getattr(currentClass, 'setUpClass', None)
1313         if setUpClass is not None:
1314+            _call_if_exists(result, '_setupStdout')
1315             try:
1316                 setUpClass()
1317-            except Exception, e:
1318+            except Exception as e:
1319                 if isinstance(result, _DebugResult):
1320                     raise
1321                 currentClass._classSetupFailed = True
1322                 className = util.strclass(currentClass)
1323                 errorName = 'setUpClass (%s)' % className
1324                 self._addClassOrModuleLevelException(result, e, errorName)
1325+            finally:
1326+                _call_if_exists(result, '_restoreStdout')
1327 
1328     def _get_previous_module(self, result):
1329         previousModule = None
1330@@ -162,7 +170,6 @@
1331 
1332         self._handleModuleTearDown(result)
1333 
1334-
1335         result._moduleSetUpFailed = False
1336         try:
1337             module = sys.modules[currentModule]
1338@@ -170,6 +177,7 @@
1339             return
1340         setUpModule = getattr(module, 'setUpModule', None)
1341         if setUpModule is not None:
1342+            _call_if_exists(result, '_setupStdout')
1343             try:
1344                 setUpModule()
1345             except Exception, e:
1346@@ -178,6 +186,8 @@
1347                 result._moduleSetUpFailed = True
1348                 errorName = 'setUpModule (%s)' % currentModule
1349                 self._addClassOrModuleLevelException(result, e, errorName)
1350+            finally:
1351+                _call_if_exists(result, '_restoreStdout')
1352 
1353     def _addClassOrModuleLevelException(self, result, exception, errorName):
1354         error = _ErrorHolder(errorName)
1355@@ -201,13 +211,16 @@
1356 
1357         tearDownModule = getattr(module, 'tearDownModule', None)
1358         if tearDownModule is not None:
1359+            _call_if_exists(result, '_setupStdout')
1360             try:
1361                 tearDownModule()
1362-            except Exception, e:
1363+            except Exception as e:
1364                 if isinstance(result, _DebugResult):
1365                     raise
1366                 errorName = 'tearDownModule (%s)' % previousModule
1367                 self._addClassOrModuleLevelException(result, e, errorName)
1368+            finally:
1369+                _call_if_exists(result, '_restoreStdout')
1370 
1371     def _tearDownPreviousClass(self, test, result):
1372         previousClass = getattr(result, '_previousTestClass', None)
1373@@ -223,6 +236,7 @@
1374 
1375         tearDownClass = getattr(previousClass, 'tearDownClass', None)
1376         if tearDownClass is not None:
1377+            _call_if_exists(result, '_setupStdout')
1378             try:
1379                 tearDownClass()
1380             except Exception, e:
1381@@ -231,6 +245,8 @@
1382                 className = util.strclass(previousClass)
1383                 errorName = 'tearDownClass (%s)' % className
1384                 self._addClassOrModuleLevelException(result, e, errorName)
1385+            finally:
1386+                _call_if_exists(result, '_restoreStdout')
1387 
1388 
1389 class _ErrorHolder(object):
1390diff -u -Naur -x .svn -x .DS_Store -x test -x '*.pyc' -w django/utils/unittest/util.py /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/util.py
1391--- django/utils/unittest/util.py       2011-05-04 23:17:48.000000000 +0200
1392+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/util.py      2011-06-11 15:50:36.000000000 +0200
1393@@ -1,7 +1,8 @@
1394 """Various utility functions."""
1395+from collections import namedtuple, OrderedDict
1396 
1397-__unittest = True
1398 
1399+__unittest = True
1400 
1401 _MAX_LENGTH = 80
1402 def safe_repr(obj, short=False):
1403@@ -13,11 +14,6 @@
1404         return result
1405     return result[:_MAX_LENGTH] + ' [truncated]...'
1406 
1407-def safe_str(obj):
1408-    try:
1409-        return str(obj)
1410-    except Exception:
1411-        return object.__str__(obj)
1412 
1413 def strclass(cls):
1414     return "%s.%s" % (cls.__module__, cls.__name__)
1415@@ -62,6 +58,7 @@
1416             break
1417     return missing, unexpected
1418 
1419+
1420 def unorderable_list_difference(expected, actual, ignore_duplicate=False):
1421     """Same behavior as sorted_list_difference but
1422     for lists of unorderable items (like dicts).
1423@@ -97,3 +94,63 @@
1424 
1425     # anything left in actual is unexpected
1426     return missing, actual
1427+
1428+_Mismatch = namedtuple('Mismatch', 'actual expected value')
1429+
1430+def _count_diff_all_purpose(actual, expected):
1431+    'Returns list of (cnt_act, cnt_exp, elem) triples where the counts differ'
1432+    # elements need not be hashable
1433+    s, t = list(actual), list(expected)
1434+    m, n = len(s), len(t)
1435+    NULL = object()
1436+    result = []
1437+    for i, elem in enumerate(s):
1438+        if elem is NULL:
1439+            continue
1440+        cnt_s = cnt_t = 0
1441+        for j in range(i, m):
1442+            if s[j] == elem:
1443+                cnt_s += 1
1444+                s[j] = NULL
1445+        for j, other_elem in enumerate(t):
1446+            if other_elem == elem:
1447+                cnt_t += 1
1448+                t[j] = NULL
1449+        if cnt_s != cnt_t:
1450+            diff = _Mismatch(cnt_s, cnt_t, elem)
1451+            result.append(diff)
1452+
1453+    for i, elem in enumerate(t):
1454+        if elem is NULL:
1455+            continue
1456+        cnt_t = 0
1457+        for j in range(i, n):
1458+            if t[j] == elem:
1459+                cnt_t += 1
1460+                t[j] = NULL
1461+        diff = _Mismatch(0, cnt_t, elem)
1462+        result.append(diff)
1463+    return result
1464+
1465+def _ordered_count(iterable):
1466+    'Return dict of element counts, in the order they were first seen'
1467+    c = OrderedDict()
1468+    for elem in iterable:
1469+        c[elem] = c.get(elem, 0) + 1
1470+    return c
1471+
1472+def _count_diff_hashable(actual, expected):
1473+    'Returns list of (cnt_act, cnt_exp, elem) triples where the counts differ'
1474+    # elements must be hashable
1475+    s, t = _ordered_count(actual), _ordered_count(expected)
1476+    result = []
1477+    for elem, cnt_s in s.items():
1478+        cnt_t = t.get(elem, 0)
1479+        if cnt_s != cnt_t:
1480+            diff = _Mismatch(cnt_s, cnt_t, elem)
1481+            result.append(diff)
1482+    for elem, cnt_t in t.items():
1483+        if elem not in s:
1484+            diff = _Mismatch(0, cnt_t, elem)
1485+            result.append(diff)
1486+    return result