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

@ -249,6 +249,8 @@ class LazyObject(object):
_wrapped = None
def __init__(self):
# Note: if a subclass overrides __init__(), it will likely need to
# override __copy__() and __deepcopy__() as well.
self._wrapped = empty
__getattr__ = new_method_proxy(getattr)
@ -301,6 +303,15 @@ class LazyObject(object):
def __getstate__(self):
return {}
def __copy__(self):
if self._wrapped is empty:
# If uninitialized, copy the wrapper. Use type(self), not
# self.__class__, because the latter is proxied.
return type(self)()
else:
# If initialized, return a copy of the wrapped object.
return copy.copy(self._wrapped)
def __deepcopy__(self, memo):
if self._wrapped is empty:
# We have to use type(self), not self.__class__, because the
@ -377,6 +388,15 @@ class SimpleLazyObject(LazyObject):
repr_attr = self._wrapped
return '<%s: %r>' % (type(self).__name__, repr_attr)
def __copy__(self):
if self._wrapped is empty:
# If uninitialized, copy the wrapper. Use SimpleLazyObject, not
# self.__class__, because the latter is proxied.
return SimpleLazyObject(self._setupfunc)
else:
# If initialized, return a copy of the wrapped object.
return copy.copy(self._wrapped)
def __deepcopy__(self, memo):
if self._wrapped is empty:
# We have to use SimpleLazyObject, not self.__class__, because the