From 13023ba86746980aace2341ba32a9419e7567751 Mon Sep 17 00:00:00 2001 From: Ben Kraft Date: Sat, 23 Jan 2016 18:02:15 -0800 Subject: Fixed #26122 -- Fixed copying a LazyObject Shallow copying of `django.utils.functional.LazyObject` or its subclasses has been broken in a couple of different ways in the past, most recently due to 35355a4. --- tests/utils_tests/test_lazyobject.py | 85 +++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 7 deletions(-) (limited to 'tests/utils_tests/test_lazyobject.py') diff --git a/tests/utils_tests/test_lazyobject.py b/tests/utils_tests/test_lazyobject.py index e0f043318c..62d7964fcf 100644 --- a/tests/utils_tests/test_lazyobject.py +++ b/tests/utils_tests/test_lazyobject.py @@ -194,28 +194,99 @@ class LazyObjectTestCase(TestCase): self.assertEqual(unpickled, obj) self.assertEqual(unpickled.foo, obj.foo) - def test_deepcopy(self): - # Check that we *can* do deep copy, and that it returns the right - # objects. + # Test copying lazy objects wrapping both builtin types and user-defined + # classes since a lot of the relevant code does __dict__ manipulation and + # builtin types don't have __dict__. + def test_copy_list(self): + # Copying a list works and returns the correct objects. l = [1, 2, 3] obj = self.lazy_wrap(l) len(l) # forces evaluation - obj2 = copy.deepcopy(obj) + obj2 = copy.copy(obj) + self.assertIsNot(obj, obj2) self.assertIsInstance(obj2, list) self.assertEqual(obj2, [1, 2, 3]) - def test_deepcopy_no_evaluation(self): - # copying doesn't force evaluation + def test_copy_list_no_evaluation(self): + # Copying a list doesn't force evaluation. + l = [1, 2, 3] + + obj = self.lazy_wrap(l) + obj2 = copy.copy(obj) + + self.assertIsNot(obj, obj2) + self.assertIs(obj._wrapped, empty) + self.assertIs(obj2._wrapped, empty) + + def test_copy_class(self): + # Copying a class works and returns the correct objects. + foo = Foo() + + obj = self.lazy_wrap(foo) + str(foo) # forces evaluation + obj2 = copy.copy(obj) + + self.assertIsNot(obj, obj2) + self.assertIsInstance(obj2, Foo) + self.assertEqual(obj2, Foo()) + + def test_copy_class_no_evaluation(self): + # Copying a class doesn't force evaluation. + foo = Foo() + + obj = self.lazy_wrap(foo) + obj2 = copy.copy(obj) + + self.assertIsNot(obj, obj2) + self.assertIs(obj._wrapped, empty) + self.assertIs(obj2._wrapped, empty) + + def test_deepcopy_list(self): + # Deep copying a list works and returns the correct objects. + l = [1, 2, 3] + + obj = self.lazy_wrap(l) + len(l) # forces evaluation + obj2 = copy.deepcopy(obj) + self.assertIsNot(obj, obj2) + self.assertIsInstance(obj2, list) + self.assertEqual(obj2, [1, 2, 3]) + + def test_deepcopy_list_no_evaluation(self): + # Deep copying doesn't force evaluation. l = [1, 2, 3] obj = self.lazy_wrap(l) obj2 = copy.deepcopy(obj) - # Copying shouldn't force evaluation + self.assertIsNot(obj, obj2) + self.assertIs(obj._wrapped, empty) + self.assertIs(obj2._wrapped, empty) + + def test_deepcopy_class(self): + # Deep copying a class works and returns the correct objects. + foo = Foo() + + obj = self.lazy_wrap(foo) + str(foo) # forces evaluation + obj2 = copy.deepcopy(obj) + + self.assertIsNot(obj, obj2) + self.assertIsInstance(obj2, Foo) + self.assertEqual(obj2, Foo()) + + def test_deepcopy_class_no_evaluation(self): + # Deep copying doesn't force evaluation. + foo = Foo() + + obj = self.lazy_wrap(foo) + obj2 = copy.deepcopy(obj) + + self.assertIsNot(obj, obj2) self.assertIs(obj._wrapped, empty) self.assertIs(obj2._wrapped, empty) -- cgit v1.3