From 655b29b5ba6200560e69bcdcfae5e2e892bddd9c Mon Sep 17 00:00:00 2001 From: Luke Plant Date: Thu, 15 Dec 2011 02:33:14 +0000 Subject: [PATCH] Fixed #16563 - Error pickling request.user Thanks to zero.fuxor for the report git-svn-id: http://code.djangoproject.com/svn/django/trunk@17202 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/utils/functional.py | 10 ++++++++++ tests/regressiontests/utils/simplelazyobject.py | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/django/utils/functional.py b/django/utils/functional.py index 1bd2286728..183c24ced3 100644 --- a/django/utils/functional.py +++ b/django/utils/functional.py @@ -261,6 +261,16 @@ class SimpleLazyObject(LazyObject): else: return copy.deepcopy(self._wrapped, memo) + # Because we have messed with __class__ below, we confuse pickle as to what + # class we are pickling. It also appears to stop __reduce__ from being + # called. So, we define __getstate__ in a way that cooperates with the way + # that pickle interprets this class. This fails when the wrapped class is a + # builtin, but it is better than nothing. + def __getstate__(self): + if self._wrapped is empty: + self._setup() + return self._wrapped.__dict__ + # Need to pretend to be the wrapped class, for the sake of objects that care # about this (especially in equality tests) __class__ = property(new_method_proxy(operator.attrgetter("__class__"))) diff --git a/tests/regressiontests/utils/simplelazyobject.py b/tests/regressiontests/utils/simplelazyobject.py index 8a02f52fb6..4ee822563e 100644 --- a/tests/regressiontests/utils/simplelazyobject.py +++ b/tests/regressiontests/utils/simplelazyobject.py @@ -1,4 +1,5 @@ import copy +import pickle from django.utils.unittest import TestCase from django.utils.functional import SimpleLazyObject, empty @@ -96,3 +97,12 @@ class TestUtilsSimpleLazyObject(TestCase): self.assertTrue(x) x = SimpleLazyObject(lambda: 0) self.assertFalse(x) + + def test_pickle_complex(self): + # See ticket #16563 + x = SimpleLazyObject(complex_object) + pickled = pickle.dumps(x) + unpickled = pickle.loads(pickled) + self.assertEqual(unpickled, x) + self.assertEqual(unicode(unpickled), unicode(x)) + self.assertEqual(unpickled.name, x.name)