From e2942d073d4b8a1f9b5f48c73855f409e6b900b2 Mon Sep 17 00:00:00 2001 From: Michael Foord Date: Thu, 2 Apr 2009 05:51:54 +0000 Subject: [PATCH] Store the functions in the _type_equality_funcs as wrapped objects that are deep copyable. This allows for the deep copying of TestCase instances. Issue 5660 --- Lib/test/test_unittest.py | 12 ++++++++++++ Lib/unittest.py | 19 +++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_unittest.py b/Lib/test/test_unittest.py index c16327e4072..38c4f8f41d0 100644 --- a/Lib/test/test_unittest.py +++ b/Lib/test/test_unittest.py @@ -11,6 +11,7 @@ from test import test_support import unittest from unittest import TestCase import types +from copy import deepcopy ### Support code ################################################################ @@ -2688,6 +2689,17 @@ test case self.failUnlessRaises(TypeError, lambda _: 3.14 + u'spam') self.failIf(False) + def testDeepcopy(self): + # Issue: 5660 + class TestableTest(TestCase): + def testNothing(self): + pass + + test = TestableTest('testNothing') + + # This shouldn't blow up + deepcopy(test) + class Test_TestSkipping(TestCase): diff --git a/Lib/unittest.py b/Lib/unittest.py index b6b96b357c0..3eedd56511c 100644 --- a/Lib/unittest.py +++ b/Lib/unittest.py @@ -160,7 +160,6 @@ def expectedFailure(func): raise _UnexpectedSuccess return wrapper - __unittest = 1 class TestResult(object): @@ -289,6 +288,16 @@ class _AssertRaisesContext(object): return True +class _AssertWrapper(object): + """Wrap entries in the _type_equality_funcs registry to make them deep + copyable.""" + + def __init__(self, function): + self.function = function + + def __deepcopy__(self, memo): + memo[id(self)] = self + class TestCase(object): """A class whose instances are single test cases. @@ -361,7 +370,7 @@ class TestCase(object): msg= argument that raises self.failureException with a useful error message when the two arguments are not equal. """ - self._type_equality_funcs[typeobj] = function + self._type_equality_funcs[typeobj] = _AssertWrapper(function) def setUp(self): "Hook method for setting up the test fixture before exercising it." @@ -542,8 +551,10 @@ class TestCase(object): # See the discussion in http://bugs.python.org/issue2578. # if type(first) is type(second): - return self._type_equality_funcs.get(type(first), - self._baseAssertEqual) + asserter = self._type_equality_funcs.get(type(first)) + if asserter is not None: + return asserter.function + return self._baseAssertEqual def _baseAssertEqual(self, first, second, msg=None):