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.
This commit is contained in:
Ben Kraft 2016-01-23 18:02:15 -08:00 committed by Tim Graham
parent cfda1fa3f8
commit 13023ba867
4 changed files with 104 additions and 7 deletions

View file

@ -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.copy(obj)
self.assertIsNot(obj, obj2)
self.assertIsInstance(obj2, list)
self.assertEqual(obj2, [1, 2, 3])
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_no_evaluation(self):
# copying doesn't force evaluation
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)