From ebfe9383bfbc53cb6c29e1170d99f64feb9ad010 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Mon, 19 Apr 2010 12:40:46 +0000 Subject: [PATCH] Fixed #13370 -- Corrected the handling of pickling for lazy() proxy objects. Thanks to Alex Gaynor for the report and patch. git-svn-id: http://code.djangoproject.com/svn/django/trunk@13000 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/utils/functional.py | 15 ++++++++------- tests/regressiontests/i18n/tests.py | 11 +++++++++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/django/utils/functional.py b/django/utils/functional.py index b66fdd3012..4b070f0ed4 100644 --- a/django/utils/functional.py +++ b/django/utils/functional.py @@ -147,11 +147,6 @@ def lazy(func, *resultclasses): the lazy evaluation code is triggered. Results are not memoized; the function is evaluated on every access. """ - # When lazy() is called by the __reduce_ex__ machinery to reconstitute the - # __proxy__ class it can't call with *args, so the first item will just be - # a tuple. - if len(resultclasses) == 1 and isinstance(resultclasses[0], tuple): - resultclasses = resultclasses[0] class __proxy__(Promise): """ @@ -168,8 +163,11 @@ def lazy(func, *resultclasses): if self.__dispatch is None: self.__prepare_class__() - def __reduce_ex__(self, protocol): - return (lazy, (self.__func, resultclasses), self.__dict__) + def __reduce__(self): + return ( + _lazy_proxy_unpickle, + (self.__func, self.__args, self.__kw) + resultclasses + ) def __prepare_class__(cls): cls.__dispatch = {} @@ -249,6 +247,9 @@ def lazy(func, *resultclasses): return wraps(func)(__wrapper__) +def _lazy_proxy_unpickle(func, args, kwargs, *resultclasses): + return lazy(func, *resultclasses)(*args, **kwargs) + def allow_lazy(func, *resultclasses): """ A decorator that allows a function to be called with one or more lazy diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py index 17e53dfa29..32c991a436 100644 --- a/tests/regressiontests/i18n/tests.py +++ b/tests/regressiontests/i18n/tests.py @@ -1,8 +1,9 @@ # -*- encoding: utf-8 -*- +import datetime +import decimal import os import sys -import decimal -import datetime +import pickle from django.template import Template, Context from django.conf import settings @@ -41,6 +42,12 @@ class TranslationTests(TestCase): s4 = ugettext_lazy('Some other string') self.assertEqual(False, s == s4) + def test_lazy_pickle(self): + s1 = ugettext_lazy("test") + self.assertEqual(unicode(s1), "test") + s2 = pickle.loads(pickle.dumps(s1)) + self.assertEqual(unicode(s2), "test") + def test_string_concat(self): """ unicode(string_concat(...)) should not raise a TypeError - #4796