diff -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
--- django/utils/unittest/__init__.py	2011-07-10 18:42:06.000000000 +0200
+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/__init__.py	2011-06-11 15:50:36.000000000 +0200
@@ -1,12 +1,30 @@
 """
-unittest2
+Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's
+Smalltalk testing framework.
 
-unittest2 is a backport of the new features added to the unittest testing
-framework in Python 2.7. It is tested to run on Python 2.4 - 2.6.
+This module contains the core framework classes that form the basis of
+specific test cases and suites (TestCase, TestSuite etc.), and also a
+text-based utility class for running the tests and reporting the results
+ (TextTestRunner).
 
-To use unittest2 instead of unittest simply replace ``import unittest`` with
-``import unittest2``.
+Simple usage:
 
+    import unittest
+
+    class IntegerArithmenticTestCase(unittest.TestCase):
+        def testAdd(self):  ## test method names begin 'test*'
+            self.assertEqual((1 + 2), 3)
+            self.assertEqual(0 + 1, 1)
+        def testMultiply(self):
+            self.assertEqual((0 * 10), 0)
+            self.assertEqual((5 * 8), 40)
+
+    if __name__ == '__main__':
+        unittest.main()
+
+Further information is available in the bundled documentation, and from
+
+  http://docs.python.org/library/unittest.html
 
 Copyright (c) 1999-2003 Steve Purcell
 Copyright (c) 2003-2010 Python Software Foundation
@@ -26,55 +44,26 @@
 SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 """
 
-import sys
-
-# Django hackery to load the appropriate version of unittest
-
-try:
-    # check the system path first
-    from unittest2 import *
-except ImportError:
-    if sys.version_info >= (2,7):
-        # unittest2 features are native in Python 2.7
-        from unittest import *
-    else:
-        # otherwise use our bundled version
         __all__ = ['TestResult', 'TestCase', 'TestSuite',
                    'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main',
                    'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless',
-                   'expectedFailure', 'TextTestResult', '__version__', 'collector']
-
-        __version__ = '0.5.1'
+           'expectedFailure', 'TextTestResult', 'installHandler',
+           'registerResult', 'removeResult', 'removeHandler']
 
         # Expose obsolete functions for backwards compatibility
         __all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
 
+__unittest = True
 
-        from django.utils.unittest.collector import collector
-        from django.utils.unittest.result import TestResult
-        from django.utils.unittest.case import \
-            TestCase, FunctionTestCase, SkipTest, skip, skipIf,\
-            skipUnless, expectedFailure
-
-        from django.utils.unittest.suite import BaseTestSuite, TestSuite
-        from django.utils.unittest.loader import \
-            TestLoader, defaultTestLoader, makeSuite, getTestCaseNames,\
-            findTestCases
-
-        from django.utils.unittest.main import TestProgram, main, main_
-        from django.utils.unittest.runner import TextTestRunner, TextTestResult
-
-        try:
-            from django.utils.unittest.signals import\
-                installHandler, registerResult, removeResult, removeHandler
-        except ImportError:
-            # Compatibility with platforms that don't have the signal module
-            pass
-        else:
-            __all__.extend(['installHandler', 'registerResult', 'removeResult',
-                            'removeHandler'])
+from .result import TestResult
+from .case import (TestCase, FunctionTestCase, SkipTest, skip, skipIf,
+                   skipUnless, expectedFailure)
+from .suite import BaseTestSuite, TestSuite
+from .loader import (TestLoader, defaultTestLoader, makeSuite, getTestCaseNames,
+                     findTestCases)
+from .main import TestProgram, main
+from .runner import TextTestRunner, TextTestResult
+from .signals import installHandler, registerResult, removeResult, removeHandler
 
         # deprecated
         _TextTestResult = TextTestResult
-
-        __unittest = True
diff -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
--- django/utils/unittest/__main__.py	2011-05-04 23:17:48.000000000 +0200
+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/__main__.py	2011-06-11 15:50:36.000000000 +0200
@@ -2,9 +2,11 @@
 
 import sys
 if sys.argv[0].endswith("__main__.py"):
-    sys.argv[0] = "unittest2"
+    sys.argv[0] = "python -m unittest"
 
 __unittest = True
 
-from django.utils.unittest.main import main_
-main_()
+from .main import main, TestProgram, USAGE_AS_MAIN
+TestProgram.USAGE = USAGE_AS_MAIN
+
+main(module=None)
diff -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
--- django/utils/unittest/case.py	2011-07-10 20:15:49.000000000 +0200
+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/case.py	2011-06-11 15:50:36.000000000 +0200
@@ -1,18 +1,19 @@
 """Test case implementation"""
 
+import collections
 import sys
+import functools
 import difflib
 import pprint
 import re
-import unittest
 import warnings
 
-from django.utils.unittest import result
-from django.utils.unittest.util import\
-    safe_repr, safe_str, strclass,\
-    unorderable_list_difference
+from . import result
+from .util import (
+    strclass, safe_repr, unorderable_list_difference,
+    _count_diff_all_purpose, _count_diff_hashable
+)
 
-from django.utils.unittest.compatibility import wraps
 
 __unittest = True
 
@@ -27,6 +28,7 @@
     Usually you can use TestResult.skip() or one of the skipping decorators
     instead of raising this directly.
     """
+    pass
 
 class _ExpectedFailure(Exception):
     """
@@ -36,14 +38,14 @@
     """
 
     def __init__(self, exc_info):
-        # can't use super because Python 2.4 exceptions are old style
-        Exception.__init__(self)
+        super(_ExpectedFailure, self).__init__()
         self.exc_info = exc_info
 
 class _UnexpectedSuccess(Exception):
     """
     The test was supposed to fail, but it didn't!
     """
+    pass
 
 def _id(obj):
     return obj
@@ -54,7 +56,7 @@
     """
     def decorator(test_item):
         if not (isinstance(test_item, type) and issubclass(test_item, TestCase)):
-            @wraps(test_item)
+            @functools.wraps(test_item)
             def skip_wrapper(*args, **kwargs):
                 raise SkipTest(reason)
             test_item = skip_wrapper
@@ -82,7 +84,7 @@
 
 
 def expectedFailure(func):
-    @wraps(func)
+    @functools.wraps(func)
     def wrapper(*args, **kwargs):
         try:
             func(*args, **kwargs)
@@ -110,7 +112,7 @@
             except AttributeError:
                 exc_name = str(self.expected)
             raise self.failureException(
-                "%s not raised" % (exc_name,))
+                "{0} not raised".format(exc_name))
         if not issubclass(exc_type, self.expected):
             # let unexpected exceptions pass through
             return False
@@ -127,28 +129,7 @@
         return True
 
 
-class _TypeEqualityDict(object):
-
-    def __init__(self, testcase):
-        self.testcase = testcase
-        self._store = {}
-
-    def __setitem__(self, key, value):
-        self._store[key] = value
-
-    def __getitem__(self, key):
-        value = self._store[key]
-        if isinstance(value, basestring):
-            return getattr(self.testcase, value)
-        return value
-
-    def get(self, key, default=None):
-        if key in self._store:
-            return self[key]
-        return default
-
-
-class TestCase(unittest.TestCase):
+class TestCase(object):
     """A class whose instances are single test cases.
 
     By default, the test code itself should be placed in a method named
@@ -176,17 +157,21 @@
 
     failureException = AssertionError
 
+    # This attribute determines whether long messages (including repr of
+    # objects used in assert methods) will be printed on failure in *addition*
+    # to any explicit message passed.
+
+    longMessage = False
+
     # This attribute sets the maximum length of a diff in failure messages
     # by assert methods using difflib. It is looked up as an instance attribute
     # so can be configured by individual tests if required.
 
     maxDiff = 80*8
 
-    # This attribute determines whether long messages (including repr of
-    # objects used in assert methods) will be printed on failure in *addition*
-    # to any explicit message passed.
-
-    longMessage = True
+    # If a string is longer than _diffThreshold, use normal comparison instead
+    # of difflib.  See #11763.
+    _diffThreshold = 2**16
 
     # Attribute used by TestSuite for classSetUp
 
@@ -202,7 +187,7 @@
         try:
             testMethod = getattr(self, methodName)
         except AttributeError:
-            raise ValueError("no such test method in %s: %s" % \
+            raise ValueError("no such test method in %s: %s" %
                   (self.__class__, methodName))
         self._testMethodDoc = testMethod.__doc__
         self._cleanups = []
@@ -210,13 +195,13 @@
         # Map types to custom assertEqual functions that will compare
         # instances of said type in more detail to generate a more useful
         # error message.
-        self._type_equality_funcs = _TypeEqualityDict(self)
-        self.addTypeEqualityFunc(dict, 'assertDictEqual')
-        self.addTypeEqualityFunc(list, 'assertListEqual')
-        self.addTypeEqualityFunc(tuple, 'assertTupleEqual')
-        self.addTypeEqualityFunc(set, 'assertSetEqual')
-        self.addTypeEqualityFunc(frozenset, 'assertSetEqual')
-        self.addTypeEqualityFunc(unicode, 'assertMultiLineEqual')
+        self._type_equality_funcs = {}
+        self.addTypeEqualityFunc(dict, self.assertDictEqual)
+        self.addTypeEqualityFunc(list, self.assertListEqual)
+        self.addTypeEqualityFunc(tuple, self.assertTupleEqual)
+        self.addTypeEqualityFunc(set, self.assertSetEqual)
+        self.addTypeEqualityFunc(frozenset, self.assertSetEqual)
+        self.addTypeEqualityFunc(unicode, self.assertMultiLineEqual)
 
     def addTypeEqualityFunc(self, typeobj, function):
         """Add a type specific assertEqual style function to compare a type.
@@ -243,6 +228,11 @@
 
     def setUp(self):
         "Hook method for setting up the test fixture before exercising it."
+        pass
+
+    def tearDown(self):
+        "Hook method for deconstructing the test fixture after testing it."
+        pass
 
     @classmethod
     def setUpClass(cls):
@@ -252,9 +242,6 @@
     def tearDownClass(cls):
         "Hook method for deconstructing the class fixture after running all tests in the class."
 
-    def tearDown(self):
-        "Hook method for deconstructing the test fixture after testing it."
-
     def countTestCases(self):
         return 1
 
@@ -299,8 +286,8 @@
         if addSkip is not None:
             addSkip(self, reason)
         else:
-            warnings.warn("Use of a TestResult without an addSkip method is deprecated",
-                          DeprecationWarning, 2)
+            warnings.warn("TestResult has no addSkip method, skips not reported",
+                          RuntimeWarning, 2)
             result.addSuccess(self)
 
     def run(self, result=None):
@@ -315,7 +302,6 @@
         result.startTest(self)
 
         testMethod = getattr(self, self._testMethodName)
-
         if (getattr(self.__class__, "__unittest_skip__", False) or
             getattr(testMethod, "__unittest_skip__", False)):
             # If the class or method was skipped.
@@ -330,41 +316,47 @@
             success = False
             try:
                 self.setUp()
-            except SkipTest, e:
+            except SkipTest as e:
                 self._addSkip(result, str(e))
-            except Exception:
+            except KeyboardInterrupt:
+                raise
+            except:
                 result.addError(self, sys.exc_info())
             else:
                 try:
                     testMethod()
+                except KeyboardInterrupt:
+                    raise
                 except self.failureException:
                     result.addFailure(self, sys.exc_info())
-                except _ExpectedFailure, e:
+                except _ExpectedFailure as e:
                     addExpectedFailure = getattr(result, 'addExpectedFailure', None)
                     if addExpectedFailure is not None:
                         addExpectedFailure(self, e.exc_info)
                     else:
-                        warnings.warn("Use of a TestResult without an addExpectedFailure method is deprecated",
-                                      DeprecationWarning)
+                        warnings.warn("TestResult has no addExpectedFailure method, reporting as passes",
+                                      RuntimeWarning)
                         result.addSuccess(self)
                 except _UnexpectedSuccess:
                     addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess', None)
                     if addUnexpectedSuccess is not None:
                         addUnexpectedSuccess(self)
                     else:
-                        warnings.warn("Use of a TestResult without an addUnexpectedSuccess method is deprecated",
-                                      DeprecationWarning)
+                        warnings.warn("TestResult has no addUnexpectedSuccess method, reporting as failures",
+                                      RuntimeWarning)
                         result.addFailure(self, sys.exc_info())
-                except SkipTest, e:
+                except SkipTest as e:
                     self._addSkip(result, str(e))
-                except Exception:
+                except:
                     result.addError(self, sys.exc_info())
                 else:
                     success = True
 
                 try:
                     self.tearDown()
-                except Exception:
+                except KeyboardInterrupt:
+                    raise
+                except:
                     result.addError(self, sys.exc_info())
                     success = False
 
@@ -388,7 +380,9 @@
             function, args, kwargs = self._cleanups.pop(-1)
             try:
                 function(*args, **kwargs)
-            except Exception:
+            except KeyboardInterrupt:
+                raise
+            except:
                 ok = False
                 result.addError(self, sys.exc_info())
         return ok
@@ -414,15 +408,15 @@
         raise self.failureException(msg)
 
     def assertFalse(self, expr, msg=None):
-        "Fail the test if the expression is true."
+        """Check that the expression is false."""
         if expr:
-            msg = self._formatMessage(msg, "%s is not False" % safe_repr(expr))
+            msg = self._formatMessage(msg, "%s is not false" % safe_repr(expr))
             raise self.failureException(msg)
 
     def assertTrue(self, expr, msg=None):
-        """Fail the test unless the expression is true."""
+        """Check that the expression is true."""
         if not expr:
-            msg = self._formatMessage(msg, "%s is not True" % safe_repr(expr))
+            msg = self._formatMessage(msg, "%s is not true" % safe_repr(expr))
             raise self.failureException(msg)
 
     def _formatMessage(self, msg, standardMsg):
@@ -440,9 +434,11 @@
         if msg is None:
             return standardMsg
         try:
+            # don't switch to '{}' formatting in Python 2.X
+            # it changes the way unicode input is handled
             return '%s : %s' % (standardMsg, msg)
         except UnicodeDecodeError:
-            return '%s : %s' % (safe_str(standardMsg), safe_str(msg))
+            return  '%s : %s' % (safe_repr(standardMsg), safe_repr(msg))
 
 
     def assertRaises(self, excClass, callableObj=None, *args, **kwargs):
@@ -468,18 +464,11 @@
                the_exception = cm.exception
                self.assertEqual(the_exception.error_code, 3)
         """
+        context = _AssertRaisesContext(excClass, self)
         if callableObj is None:
-            return _AssertRaisesContext(excClass, self)
-        try:
+            return context
+        with context:
             callableObj(*args, **kwargs)
-        except excClass:
-            return
-
-        if hasattr(excClass,'__name__'):
-            excName = excClass.__name__
-        else:
-            excName = str(excClass)
-        raise self.failureException("%s not raised" % excName)
 
     def _getAssertEqualityFunc(self, first, second):
         """Get a detailed comparison function for the types of the two args.
@@ -528,6 +517,7 @@
                                                            safe_repr(second)))
             raise self.failureException(msg)
 
+
     def assertAlmostEqual(self, first, second, places=None, msg=None, delta=None):
         """Fail if the two objects are unequal as determined by their
            difference rounded to the given number of decimal places
@@ -613,7 +603,7 @@
     def _deprecate(original_func):
         def deprecated_func(*args, **kwargs):
             warnings.warn(
-                ('Please use %s instead.' % original_func.__name__),
+                'Please use {0} instead.'.format(original_func.__name__),
                 PendingDeprecationWarning, 2)
             return original_func(*args, **kwargs)
         return deprecated_func
@@ -626,8 +616,7 @@
     failUnlessRaises = _deprecate(assertRaises)
     failIf = _deprecate(assertFalse)
 
-    def assertSequenceEqual(self, seq1, seq2,
-                            msg=None, seq_type=None, max_diff=80*8):
+    def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
         """An equality assertion for ordered sequences (like lists and tuples).
 
         For the purposes of this function, a valid ordered sequence type is one
@@ -640,7 +629,6 @@
                     datatype should be enforced.
             msg: Optional message to use on failure instead of a list of
                     differences.
-            max_diff: Maximum size off the diff, larger diffs are not shown
         """
         if seq_type is not None:
             seq_type_name = seq_type.__name__
@@ -671,8 +659,8 @@
             if seq1 == seq2:
                 return
 
-            seq1_repr = repr(seq1)
-            seq2_repr = repr(seq2)
+            seq1_repr = safe_repr(seq1)
+            seq2_repr = safe_repr(seq2)
             if len(seq1_repr) > 30:
                 seq1_repr = seq1_repr[:30] + '...'
             if len(seq2_repr) > 30:
@@ -727,7 +715,6 @@
         diffMsg = '\n' + '\n'.join(
             difflib.ndiff(pprint.pformat(seq1).splitlines(),
                           pprint.pformat(seq2).splitlines()))
-
         standardMsg = self._truncateMessage(standardMsg, diffMsg)
         msg = self._formatMessage(msg, standardMsg)
         self.fail(msg)
@@ -770,9 +757,9 @@
             msg: Optional message to use on failure instead of a list of
                     differences.
 
-        assertSetEqual uses ducktyping to support
-        different types of sets, and is optimized for sets specifically
-        (parameters must support a difference method).
+        assertSetEqual uses ducktyping to support different types of sets, and
+        is optimized for sets specifically (parameters must support a
+        difference method).
         """
         try:
             difference1 = set1.difference(set2)
@@ -821,7 +808,8 @@
     def assertIs(self, expr1, expr2, msg=None):
         """Just like self.assertTrue(a is b), but with a nicer default message."""
         if expr1 is not expr2:
-            standardMsg = '%s is not %s' % (safe_repr(expr1), safe_repr(expr2))
+            standardMsg = '%s is not %s' % (safe_repr(expr1),
+                                             safe_repr(expr2))
             self.fail(self._formatMessage(msg, standardMsg))
 
     def assertIsNot(self, expr1, expr2, msg=None):
@@ -831,8 +819,8 @@
             self.fail(self._formatMessage(msg, standardMsg))
 
     def assertDictEqual(self, d1, d2, msg=None):
-        self.assertTrue(isinstance(d1, dict), 'First argument is not a dictionary')
-        self.assertTrue(isinstance(d2, dict), 'Second argument is not a dictionary')
+        self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
+        self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')
 
         if d1 != d2:
             standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True))
@@ -870,54 +858,64 @@
 
     def assertItemsEqual(self, expected_seq, actual_seq, msg=None):
         """An unordered sequence specific comparison. It asserts that
-        expected_seq and actual_seq contain the same elements. It is
-        the equivalent of::
+        actual_seq and expected_seq have the same element counts.
+        Equivalent to::
 
-            self.assertEqual(sorted(expected_seq), sorted(actual_seq))
-
-        Raises with an error message listing which elements of expected_seq
-        are missing from actual_seq and vice versa if any.
+            self.assertEqual(Counter(iter(actual_seq)),
+                             Counter(iter(expected_seq)))
 
         Asserts that each element has the same count in both sequences.
         Example:
             - [0, 1, 1] and [1, 0, 1] compare equal.
             - [0, 0, 1] and [0, 1] compare unequal.
         """
+        first_seq, second_seq = list(actual_seq), list(expected_seq)
+        with warnings.catch_warnings():
+            if sys.py3kwarning:
+                # Silence Py3k warning raised during the sorting
+                for _msg in ["(code|dict|type) inequality comparisons",
+                             "builtin_function_or_method order comparisons",
+                             "comparing unequal types"]:
+                    warnings.filterwarnings("ignore", _msg, DeprecationWarning)
         try:
-            expected = sorted(expected_seq)
-            actual = sorted(actual_seq)
+                first = collections.Counter(first_seq)
+                second = collections.Counter(second_seq)
         except TypeError:
-            # Unsortable items (example: set(), complex(), ...)
-            expected = list(expected_seq)
-            actual = list(actual_seq)
-            missing, unexpected = unorderable_list_difference(
-                expected, actual, ignore_duplicate=False
-            )
+                # Handle case with unhashable elements
+                differences = _count_diff_all_purpose(first_seq, second_seq)
         else:
-            return self.assertSequenceEqual(expected, actual, msg=msg)
+                if first == second:
+                    return
+                differences = _count_diff_hashable(first_seq, second_seq)
 
-        errors = []
-        if missing:
-            errors.append('Expected, but missing:\n    %s' %
-                           safe_repr(missing))
-        if unexpected:
-            errors.append('Unexpected, but present:\n    %s' %
-                           safe_repr(unexpected))
-        if errors:
-            standardMsg = '\n'.join(errors)
-            self.fail(self._formatMessage(msg, standardMsg))
+        if differences:
+            standardMsg = 'Element counts were not equal:\n'
+            lines = ['First has %d, Second has %d:  %r' % diff for diff in differences]
+            diffMsg = '\n'.join(lines)
+            standardMsg = self._truncateMessage(standardMsg, diffMsg)
+            msg = self._formatMessage(msg, standardMsg)
+            self.fail(msg)
 
     def assertMultiLineEqual(self, first, second, msg=None):
         """Assert that two multi-line strings are equal."""
-        self.assertTrue(isinstance(first, basestring), (
-                'First argument is not a string'))
-        self.assertTrue(isinstance(second, basestring), (
-                'Second argument is not a string'))
+        self.assertIsInstance(first, basestring,
+                'First argument is not a string')
+        self.assertIsInstance(second, basestring,
+                'Second argument is not a string')
 
         if first != second:
-            standardMsg = '%s != %s' % (safe_repr(first, True), safe_repr(second, True))
-            diff = '\n' + ''.join(difflib.ndiff(first.splitlines(True),
-                                                       second.splitlines(True)))
+            # don't use difflib if the strings are too long
+            if (len(first) > self._diffThreshold or
+                len(second) > self._diffThreshold):
+                self._baseAssertEqual(first, second, msg)
+            firstlines = first.splitlines(True)
+            secondlines = second.splitlines(True)
+            if len(firstlines) == 1 and first.strip('\r\n') == first:
+                firstlines = [first + '\n']
+                secondlines = [second + '\n']
+            standardMsg = '%s != %s' % (safe_repr(first, True),
+                                        safe_repr(second, True))
+            diff = '\n' + ''.join(difflib.ndiff(firstlines, secondlines))
             standardMsg = self._truncateMessage(standardMsg, diff)
             self.fail(self._formatMessage(msg, standardMsg))
 
@@ -982,22 +980,11 @@
             args: Extra args.
             kwargs: Extra kwargs.
         """
+        context = _AssertRaisesContext(expected_exception, self, expected_regexp)
         if callable_obj is None:
-            return _AssertRaisesContext(expected_exception, self, expected_regexp)
-        try:
+            return context
+        with context:
             callable_obj(*args, **kwargs)
-        except expected_exception, exc_value:
-            if isinstance(expected_regexp, basestring):
-                expected_regexp = re.compile(expected_regexp)
-            if not expected_regexp.search(str(exc_value)):
-                raise self.failureException('"%s" does not match "%s"' %
-                         (expected_regexp.pattern, str(exc_value)))
-        else:
-            if hasattr(expected_exception, '__name__'):
-                excName = expected_exception.__name__
-            else:
-                excName = str(expected_exception)
-            raise self.failureException("%s not raised" % excName)
 
     def assertRegexpMatches(self, text, expected_regexp, msg=None):
         """Fail the test unless the text matches the regular expression."""
@@ -1021,6 +1008,7 @@
                                                text)
             raise self.failureException(msg)
 
+
 class FunctionTestCase(TestCase):
     """A test case that wraps a test function.
 
@@ -1072,7 +1060,7 @@
                             self._testFunc.__name__)
 
     def __repr__(self):
-        return "<%s testFunc=%s>" % (strclass(self.__class__),
+        return "<%s tec=%s>" % (strclass(self.__class__),
                                      self._testFunc)
 
     def shortDescription(self):
diff -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
--- django/utils/unittest/collector.py	2011-05-04 23:17:48.000000000 +0200
+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/collector.py	1970-01-01 01:00:00.000000000 +0100
@@ -1,9 +0,0 @@
-import os
-import sys
-from django.utils.unittest.loader import defaultTestLoader
-
-def collector():
-    # import __main__ triggers code re-execution
-    __main__ = sys.modules['__main__']
-    setupDir = os.path.abspath(os.path.dirname(__main__.__file__))
-    return defaultTestLoader.discover(setupDir)
diff -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
--- django/utils/unittest/compatibility.py	2011-07-10 20:15:49.000000000 +0200
+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/compatibility.py	1970-01-01 01:00:00.000000000 +0100
@@ -1,64 +0,0 @@
-import os
-import sys
-
-try:
-    from functools import wraps
-except ImportError:
-    # only needed for Python 2.4
-    def wraps(_):
-        def _wraps(func):
-            return func
-        return _wraps
-
-__unittest = True
-
-def _relpath_nt(path, start=os.path.curdir):
-    """Return a relative version of a path"""
-
-    if not path:
-        raise ValueError("no path specified")
-    start_list = os.path.abspath(start).split(os.path.sep)
-    path_list = os.path.abspath(path).split(os.path.sep)
-    if start_list[0].lower() != path_list[0].lower():
-        unc_path, rest = os.path.splitunc(path)
-        unc_start, rest = os.path.splitunc(start)
-        if bool(unc_path) ^ bool(unc_start):
-            raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
-                                                                % (path, start))
-        else:
-            raise ValueError("path is on drive %s, start on drive %s"
-                                                % (path_list[0], start_list[0]))
-    # Work out how much of the filepath is shared by start and path.
-    for i in range(min(len(start_list), len(path_list))):
-        if start_list[i].lower() != path_list[i].lower():
-            break
-    else:
-        i += 1
-
-    rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
-    if not rel_list:
-        return os.path.curdir
-    return os.path.join(*rel_list)
-
-# default to posixpath definition
-def _relpath_posix(path, start=os.path.curdir):
-    """Return a relative version of a path"""
-
-    if not path:
-        raise ValueError("no path specified")
-
-    start_list = os.path.abspath(start).split(os.path.sep)
-    path_list = os.path.abspath(path).split(os.path.sep)
-
-    # Work out how much of the filepath is shared by start and path.
-    i = len(os.path.commonprefix([start_list, path_list]))
-
-    rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
-    if not rel_list:
-        return os.path.curdir
-    return os.path.join(*rel_list)
-
-if os.path is sys.modules.get('ntpath'):
-    relpath = _relpath_nt
-else:
-    relpath = _relpath_posix
diff -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
--- django/utils/unittest/loader.py	2011-05-04 23:17:48.000000000 +0200
+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/loader.py	2011-06-11 15:50:36.000000000 +0200
@@ -5,30 +5,14 @@
 import sys
 import traceback
 import types
-import unittest
 
+from functools import cmp_to_key as _CmpToKey
 from fnmatch import fnmatch
 
-from django.utils.unittest import case, suite
-
-try:
-    from os.path import relpath
-except ImportError:
-    from django.utils.unittest.compatibility import relpath
+from . import case, suite
 
 __unittest = True
 
-
-def _CmpToKey(mycmp):
-    'Convert a cmp= function into a key= function'
-    class K(object):
-        def __init__(self, obj):
-            self.obj = obj
-        def __lt__(self, other):
-            return mycmp(self.obj, other.obj) == -1
-    return K
-
-
 # what about .pyc or .pyo (etc)
 # we would need to avoid loading the same tests multiple times
 # from '.py', '.pyc' *and* '.pyo'
@@ -36,11 +20,7 @@
 
 
 def _make_failed_import_test(name, suiteClass):
-    message = 'Failed to import test module: %s' % name
-    if hasattr(traceback, 'format_exc'):
-        # Python 2.3 compatibility
-        # format_exc returns two frames of discover.py as well
-        message += '\n%s' % traceback.format_exc()
+    message = 'Failed to import test module: %s\n%s' % (name, traceback.format_exc())
     return _make_failed_test('ModuleImportFailure', name, ImportError(message),
                              suiteClass)
 
@@ -55,7 +35,7 @@
     return suiteClass((TestClass(methodname),))
 
 
-class TestLoader(unittest.TestLoader):
+class TestLoader(object):
     """
     This class is responsible for loading tests according to various criteria
     and returning them wrapped in a TestSuite
@@ -68,7 +48,7 @@
     def loadTestsFromTestCase(self, testCaseClass):
         """Return a suite of all tests cases contained in testCaseClass"""
         if issubclass(testCaseClass, suite.TestSuite):
-            raise TypeError("Test cases should not be derived from TestSuite."
+            raise TypeError("Test cases should not be derived from TestSuite." \
                             " Maybe you meant to derive from TestCase?")
         testCaseNames = self.getTestCaseNames(testCaseClass)
         if not testCaseNames and hasattr(testCaseClass, 'runTest'):
@@ -81,7 +61,7 @@
         tests = []
         for name in dir(module):
             obj = getattr(module, name)
-            if isinstance(obj, type) and issubclass(obj, unittest.TestCase):
+            if isinstance(obj, type) and issubclass(obj, case.TestCase):
                 tests.append(self.loadTestsFromTestCase(obj))
 
         load_tests = getattr(module, 'load_tests', None)
@@ -121,19 +101,19 @@
 
         if isinstance(obj, types.ModuleType):
             return self.loadTestsFromModule(obj)
-        elif isinstance(obj, type) and issubclass(obj, unittest.TestCase):
+        elif isinstance(obj, type) and issubclass(obj, case.TestCase):
             return self.loadTestsFromTestCase(obj)
         elif (isinstance(obj, types.UnboundMethodType) and
               isinstance(parent, type) and
               issubclass(parent, case.TestCase)):
             return self.suiteClass([parent(obj.__name__)])
-        elif isinstance(obj, unittest.TestSuite):
+        elif isinstance(obj, suite.TestSuite):
             return obj
         elif hasattr(obj, '__call__'):
             test = obj()
-            if isinstance(test, unittest.TestSuite):
+            if isinstance(test, suite.TestSuite):
                 return test
-            elif isinstance(test, unittest.TestCase):
+            elif isinstance(test, case.TestCase):
                 return self.suiteClass([test])
             else:
                 raise TypeError("calling %s returned %s, not a test" %
@@ -215,7 +195,7 @@
                 top_part = start_dir.split('.')[0]
                 start_dir = os.path.abspath(os.path.dirname((the_module.__file__)))
                 if set_implicit_top:
-                    self._top_level_dir = os.path.abspath(os.path.dirname(os.path.dirname(sys.modules[top_part].__file__)))
+                    self._top_level_dir = self._get_directory_containing_module(top_part)
                     sys.path.remove(top_level_dir)
 
         if is_not_importable:
@@ -224,10 +204,22 @@
         tests = list(self._find_tests(start_dir, pattern))
         return self.suiteClass(tests)
 
+    def _get_directory_containing_module(self, module_name):
+        module = sys.modules[module_name]
+        full_path = os.path.abspath(module.__file__)
+
+        if os.path.basename(full_path).lower().startswith('__init__.py'):
+            return os.path.dirname(os.path.dirname(full_path))
+        else:
+            # here we have been given a module rather than a package - so
+            # all we can do is search the *same* directory the module is in
+            # should an exception be raised instead
+            return os.path.dirname(full_path)
+
     def _get_name_from_path(self, path):
         path = os.path.splitext(os.path.normpath(path))[0]
 
-        _relpath = relpath(path, self._top_level_dir)
+        _relpath = os.path.relpath(path, self._top_level_dir)
         assert not os.path.isabs(_relpath), "Path must be within the project"
         assert not _relpath.startswith('..'), "Path must be within the project"
 
diff -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
--- django/utils/unittest/main.py	2011-05-04 23:17:48.000000000 +0200
+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/main.py	2011-06-11 15:50:36.000000000 +0200
@@ -4,11 +4,8 @@
 import os
 import types
 
-from django.utils.unittest import loader, runner
-try:
-    from django.utils.unittest.signals import installHandler
-except ImportError:
-    installHandler = None
+from . import loader, runner
+from .signals import installHandler
 
 __unittest = True
 
@@ -26,9 +23,8 @@
 %(failfast)s%(catchbreak)s%(buffer)s
 Examples:
   %(progName)s test_module                       - run tests from test_module
-  %(progName)s test_module.TestClass             - run tests from
-                                                   test_module.TestClass
-  %(progName)s test_module.TestClass.test_method - run specified test method
+  %(progName)s module.TestClass          - run tests from module.TestClass
+  %(progName)s module.Class.test_method  - run specified test method
 
 [tests] can be a list of any number of test modules, classes and test
 methods.
@@ -63,6 +59,7 @@
 """
 
 
+
 class TestProgram(object):
     """A command-line program that runs a set of tests; this is primarily
        for making test modules conveniently executable.
@@ -72,10 +69,10 @@
     # defaults for testing
     failfast = catchbreak = buffer = progName = None
 
-    def __init__(self, module='__main__', defaultTest=None,
-                 argv=None, testRunner=None,
-                 testLoader=loader.defaultTestLoader, exit=True,
-                 verbosity=1, failfast=None, catchbreak=None, buffer=None):
+    def __init__(self, module='__main__', defaultTest=None, argv=None,
+                    testRunner=None, testLoader=loader.defaultTestLoader,
+                    exit=True, verbosity=1, failfast=None, catchbreak=None,
+                    buffer=None):
         if isinstance(module, basestring):
             self.module = __import__(module)
             for part in module.split('.')[1:]:
@@ -86,9 +83,9 @@
             argv = sys.argv
 
         self.exit = exit
-        self.verbosity = verbosity
         self.failfast = failfast
         self.catchbreak = catchbreak
+        self.verbosity = verbosity
         self.buffer = buffer
         self.defaultTest = defaultTest
         self.testRunner = testRunner
@@ -104,7 +101,7 @@
                  'buffer': ''}
         if self.failfast != False:
             usage['failfast'] = FAILFAST
-        if self.catchbreak != False and installHandler is not None:
+        if self.catchbreak != False:
             usage['catchbreak'] = CATCHBREAK
         if self.buffer != False:
             usage['buffer'] = BUFFEROUTPUT
@@ -132,7 +129,7 @@
                         self.failfast = True
                     # Should this raise an exception if -f is not valid?
                 if opt in ('-c','--catch'):
-                    if self.catchbreak is None and installHandler is not None:
+                    if self.catchbreak is None:
                         self.catchbreak = True
                     # Should this raise an exception if -c is not valid?
                 if opt in ('-b','--buffer'):
@@ -172,7 +169,7 @@
             parser.add_option('-f', '--failfast', dest='failfast', default=False,
                               help='Stop on first fail or error',
                               action='store_true')
-        if self.catchbreak != False and installHandler is not None:
+        if self.catchbreak != False:
             parser.add_option('-c', '--catch', dest='catchbreak', default=False,
                               help='Catch ctrl-C and display results so far',
                               action='store_true')
@@ -198,7 +195,7 @@
         # if they weren't set explicitly in the constructor
         if self.failfast is None:
             self.failfast = options.failfast
-        if self.catchbreak is None and installHandler is not None:
+        if self.catchbreak is None:
             self.catchbreak = options.catchbreak
         if self.buffer is None:
             self.buffer = options.buffer
@@ -234,8 +231,3 @@
             sys.exit(not self.result.wasSuccessful())
 
 main = TestProgram
-
-def main_():
-    TestProgram.USAGE = USAGE_AS_MAIN
-    main(module=None)
-
diff -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
--- django/utils/unittest/result.py	2011-07-10 20:15:49.000000000 +0200
+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/result.py	2011-06-11 15:50:36.000000000 +0200
@@ -1,13 +1,13 @@
 """Test result object"""
 
+import os
 import sys
 import traceback
-import unittest
 
 from StringIO import StringIO
 
-from django.utils.unittest import util
-from django.utils.unittest.compatibility import wraps
+from . import util
+from functools import wraps
 
 __unittest = True
 
@@ -19,11 +19,11 @@
         return method(self, *args, **kw)
     return inner
 
-
 STDOUT_LINE = '\nStdout:\n%s'
 STDERR_LINE = '\nStderr:\n%s'
 
-class TestResult(unittest.TestResult):
+
+class TestResult(object):
     """Holder for test result information.
 
     Test results are automatically managed by the TestCase and TestSuite
@@ -35,9 +35,9 @@
     formatted traceback of the error that occurred.
     """
     _previousTestClass = None
+    _testRunEntered = False
     _moduleSetUpFailed = False
-
-    def __init__(self):
+    def __init__(self, stream=None, descriptions=None, verbosity=None):
         self.failfast = False
         self.failures = []
         self.errors = []
@@ -53,10 +53,16 @@
         self._original_stderr = sys.stderr
         self._mirrorOutput = False
 
+    def printErrors(self):
+        "Called by TestRunner after test run"
+
     def startTest(self, test):
         "Called when the given test is about to be run"
         self.testsRun += 1
         self._mirrorOutput = False
+        self._setupStdout()
+
+    def _setupStdout(self):
         if self.buffer:
             if self._stderr_buffer is None:
                 self._stderr_buffer = StringIO()
@@ -72,6 +78,10 @@
 
     def stopTest(self, test):
         """Called when the given test has been run"""
+        self._restoreStdout()
+        self._mirrorOutput = False
+
+    def _restoreStdout(self):
         if self.buffer:
             if self._mirrorOutput:
                 output = sys.stdout.getvalue()
@@ -91,8 +101,6 @@
             self._stdout_buffer.truncate()
             self._stderr_buffer.seek(0)
             self._stderr_buffer.truncate()
-        self._mirrorOutput = False
-
 
     def stopTestRun(self):
         """Called once after all tests are executed.
@@ -135,7 +143,7 @@
 
     def wasSuccessful(self):
         "Tells whether or not this result was a success"
-        return (len(self.failures) + len(self.errors) == 0)
+        return len(self.failures) == len(self.errors) == 0
 
     def stop(self):
         "Indicates that the tests should be aborted"
@@ -147,6 +155,7 @@
         # Skip test runner traceback levels
         while tb and self._is_relevant_tb_level(tb):
             tb = tb.tb_next
+
         if exctype is test.failureException:
             # Skip assert*() traceback levels
             length = self._count_relevant_tb_levels(tb)
@@ -167,6 +176,7 @@
                 msgLines.append(STDERR_LINE % error)
         return ''.join(msgLines)
 
+
     def _is_relevant_tb_level(self, tb):
         return '__unittest' in tb.tb_frame.f_globals
 
@@ -178,6 +188,6 @@
         return length
 
     def __repr__(self):
-        return "<%s run=%i errors=%i failures=%i>" % \
+        return ("<%s run=%i errors=%i failures=%i>" %
                (util.strclass(self.__class__), self.testsRun, len(self.errors),
-                len(self.failures))
+                len(self.failures)))
diff -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
--- django/utils/unittest/runner.py	2011-05-04 23:17:48.000000000 +0200
+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/runner.py	2011-06-11 15:50:36.000000000 +0200
@@ -2,15 +2,9 @@
 
 import sys
 import time
-import unittest
 
-from django.utils.unittest import result
-
-try:
-    from django.utils.unittest.signals import registerResult
-except ImportError:
-    def registerResult(_):
-        pass
+from . import result
+from .signals import registerResult
 
 __unittest = True
 
@@ -87,7 +81,7 @@
     def addSkip(self, test, reason):
         super(TextTestResult, self).addSkip(test, reason)
         if self.showAll:
-            self.stream.writeln("skipped %r" % (reason,))
+            self.stream.writeln("skipped {0!r}".format(reason))
         elif self.dots:
             self.stream.write("s")
             self.stream.flush()
@@ -121,12 +115,8 @@
             self.stream.writeln(self.separator2)
             self.stream.writeln("%s" % err)
 
-    def stopTestRun(self):
-        super(TextTestResult, self).stopTestRun()
-        self.printErrors()
-
 
-class TextTestRunner(unittest.TextTestRunner):
+class TextTestRunner(object):
     """A test runner class that displays results in textual form.
 
     It prints out the names of tests as they are run, errors as they
@@ -150,10 +140,9 @@
     def run(self, test):
         "Run the given test case or test suite."
         result = self._makeResult()
+        registerResult(result)
         result.failfast = self.failfast
         result.buffer = self.buffer
-        registerResult(result)
-
         startTime = time.time()
         startTestRun = getattr(result, 'startTestRun', None)
         if startTestRun is not None:
@@ -164,10 +153,9 @@
             stopTestRun = getattr(result, 'stopTestRun', None)
             if stopTestRun is not None:
                 stopTestRun()
-            else:
-                result.printErrors()
         stopTime = time.time()
         timeTaken = stopTime - startTime
+        result.printErrors()
         if hasattr(result, 'separator2'):
             self.stream.writeln(result.separator2)
         run = result.testsRun
@@ -180,9 +168,11 @@
             results = map(len, (result.expectedFailures,
                                 result.unexpectedSuccesses,
                                 result.skipped))
-            expectedFails, unexpectedSuccesses, skipped = results
         except AttributeError:
             pass
+        else:
+            expectedFails, unexpectedSuccesses, skipped = results
+
         infos = []
         if not result.wasSuccessful():
             self.stream.write("FAILED")
diff -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
--- django/utils/unittest/signals.py	2011-07-10 20:15:49.000000000 +0200
+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/signals.py	2011-06-11 15:50:36.000000000 +0200
@@ -1,7 +1,7 @@
 import signal
 import weakref
 
-from django.utils.unittest.compatibility import wraps
+from functools import wraps
 
 __unittest = True
 
diff -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
--- django/utils/unittest/suite.py	2011-05-04 23:17:48.000000000 +0200
+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/suite.py	2011-06-11 15:50:36.000000000 +0200
@@ -1,13 +1,19 @@
 """TestSuite"""
 
 import sys
-import unittest
-from django.utils.unittest import case, util
+
+from . import case
+from . import util
 
 __unittest = True
 
 
-class BaseTestSuite(unittest.TestSuite):
+def _call_if_exists(parent, attr):
+    func = getattr(parent, attr, lambda: None)
+    func()
+
+
+class BaseTestSuite(object):
     """A simple test suite that doesn't provide class or module shared fixtures.
     """
     def __init__(self, tests=()):
@@ -40,7 +46,7 @@
     def addTest(self, test):
         # sanity checks
         if not hasattr(test, '__call__'):
-            raise TypeError("%r is not callable" % (repr(test),))
+            raise TypeError("{} is not callable".format(repr(test)))
         if isinstance(test, type) and issubclass(test,
                                                  (case.TestCase, TestSuite)):
             raise TypeError("TestCases and TestSuites must be instantiated "
@@ -79,23 +85,11 @@
     subclassing, do not forget to call the base class constructor.
     """
 
+    def run(self, result, debug=False):
+        topLevel = False
+        if getattr(result, '_testRunEntered', False) is False:
+            result._testRunEntered = topLevel = True
 
-    def run(self, result):
-        self._wrapped_run(result)
-        self._tearDownPreviousClass(None, result)
-        self._handleModuleTearDown(result)
-        return result
-
-    def debug(self):
-        """Run the tests without collecting errors in a TestResult"""
-        debug = _DebugResult()
-        self._wrapped_run(debug, True)
-        self._tearDownPreviousClass(None, debug)
-        self._handleModuleTearDown(debug)
-
-    ################################
-    # private methods
-    def _wrapped_run(self, result, debug=False):
         for test in self:
             if result.shouldStop:
                 break
@@ -110,13 +104,24 @@
                     getattr(result, '_moduleSetUpFailed', False)):
                     continue
 
-            if hasattr(test, '_wrapped_run'):
-                test._wrapped_run(result, debug)
-            elif not debug:
+            if not debug:
                 test(result)
             else:
                 test.debug()
 
+        if topLevel:
+            self._tearDownPreviousClass(None, result)
+            self._handleModuleTearDown(result)
+            result._testRunEntered = False
+        return result
+
+    def debug(self):
+        """Run the tests without collecting errors in a TestResult"""
+        debug = _DebugResult()
+        self.run(debug, True)
+
+    ################################
+
     def _handleClassSetUp(self, test, result):
         previousClass = getattr(result, '_previousTestClass', None)
         currentClass = test.__class__
@@ -136,15 +141,18 @@
 
         setUpClass = getattr(currentClass, 'setUpClass', None)
         if setUpClass is not None:
+            _call_if_exists(result, '_setupStdout')
             try:
                 setUpClass()
-            except Exception, e:
+            except Exception as e:
                 if isinstance(result, _DebugResult):
                     raise
                 currentClass._classSetupFailed = True
                 className = util.strclass(currentClass)
                 errorName = 'setUpClass (%s)' % className
                 self._addClassOrModuleLevelException(result, e, errorName)
+            finally:
+                _call_if_exists(result, '_restoreStdout')
 
     def _get_previous_module(self, result):
         previousModule = None
@@ -162,7 +170,6 @@
 
         self._handleModuleTearDown(result)
 
-
         result._moduleSetUpFailed = False
         try:
             module = sys.modules[currentModule]
@@ -170,6 +177,7 @@
             return
         setUpModule = getattr(module, 'setUpModule', None)
         if setUpModule is not None:
+            _call_if_exists(result, '_setupStdout')
             try:
                 setUpModule()
             except Exception, e:
@@ -178,6 +186,8 @@
                 result._moduleSetUpFailed = True
                 errorName = 'setUpModule (%s)' % currentModule
                 self._addClassOrModuleLevelException(result, e, errorName)
+            finally:
+                _call_if_exists(result, '_restoreStdout')
 
     def _addClassOrModuleLevelException(self, result, exception, errorName):
         error = _ErrorHolder(errorName)
@@ -201,13 +211,16 @@
 
         tearDownModule = getattr(module, 'tearDownModule', None)
         if tearDownModule is not None:
+            _call_if_exists(result, '_setupStdout')
             try:
                 tearDownModule()
-            except Exception, e:
+            except Exception as e:
                 if isinstance(result, _DebugResult):
                     raise
                 errorName = 'tearDownModule (%s)' % previousModule
                 self._addClassOrModuleLevelException(result, e, errorName)
+            finally:
+                _call_if_exists(result, '_restoreStdout')
 
     def _tearDownPreviousClass(self, test, result):
         previousClass = getattr(result, '_previousTestClass', None)
@@ -223,6 +236,7 @@
 
         tearDownClass = getattr(previousClass, 'tearDownClass', None)
         if tearDownClass is not None:
+            _call_if_exists(result, '_setupStdout')
             try:
                 tearDownClass()
             except Exception, e:
@@ -231,6 +245,8 @@
                 className = util.strclass(previousClass)
                 errorName = 'tearDownClass (%s)' % className
                 self._addClassOrModuleLevelException(result, e, errorName)
+            finally:
+                _call_if_exists(result, '_restoreStdout')
 
 
 class _ErrorHolder(object):
diff -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
--- django/utils/unittest/util.py	2011-05-04 23:17:48.000000000 +0200
+++ /Users/myk/Downloads/cpython-eb3c9b74884c/Lib/unittest/util.py	2011-06-11 15:50:36.000000000 +0200
@@ -1,7 +1,8 @@
 """Various utility functions."""
+from collections import namedtuple, OrderedDict
 
-__unittest = True
 
+__unittest = True
 
 _MAX_LENGTH = 80
 def safe_repr(obj, short=False):
@@ -13,11 +14,6 @@
         return result
     return result[:_MAX_LENGTH] + ' [truncated]...'
 
-def safe_str(obj):
-    try:
-        return str(obj)
-    except Exception:
-        return object.__str__(obj)
 
 def strclass(cls):
     return "%s.%s" % (cls.__module__, cls.__name__)
@@ -62,6 +58,7 @@
             break
     return missing, unexpected
 
+
 def unorderable_list_difference(expected, actual, ignore_duplicate=False):
     """Same behavior as sorted_list_difference but
     for lists of unorderable items (like dicts).
@@ -97,3 +94,63 @@
 
     # anything left in actual is unexpected
     return missing, actual
+
+_Mismatch = namedtuple('Mismatch', 'actual expected value')
+
+def _count_diff_all_purpose(actual, expected):
+    'Returns list of (cnt_act, cnt_exp, elem) triples where the counts differ'
+    # elements need not be hashable
+    s, t = list(actual), list(expected)
+    m, n = len(s), len(t)
+    NULL = object()
+    result = []
+    for i, elem in enumerate(s):
+        if elem is NULL:
+            continue
+        cnt_s = cnt_t = 0
+        for j in range(i, m):
+            if s[j] == elem:
+                cnt_s += 1
+                s[j] = NULL
+        for j, other_elem in enumerate(t):
+            if other_elem == elem:
+                cnt_t += 1
+                t[j] = NULL
+        if cnt_s != cnt_t:
+            diff = _Mismatch(cnt_s, cnt_t, elem)
+            result.append(diff)
+
+    for i, elem in enumerate(t):
+        if elem is NULL:
+            continue
+        cnt_t = 0
+        for j in range(i, n):
+            if t[j] == elem:
+                cnt_t += 1
+                t[j] = NULL
+        diff = _Mismatch(0, cnt_t, elem)
+        result.append(diff)
+    return result
+
+def _ordered_count(iterable):
+    'Return dict of element counts, in the order they were first seen'
+    c = OrderedDict()
+    for elem in iterable:
+        c[elem] = c.get(elem, 0) + 1
+    return c
+
+def _count_diff_hashable(actual, expected):
+    'Returns list of (cnt_act, cnt_exp, elem) triples where the counts differ'
+    # elements must be hashable
+    s, t = _ordered_count(actual), _ordered_count(expected)
+    result = []
+    for elem, cnt_s in s.items():
+        cnt_t = t.get(elem, 0)
+        if cnt_s != cnt_t:
+            diff = _Mismatch(cnt_s, cnt_t, elem)
+            result.append(diff)
+    for elem, cnt_t in t.items():
+        if elem not in s:
+            diff = _Mismatch(0, cnt_t, elem)
+            result.append(diff)
+    return result
