summaryrefslogtreecommitdiff
path: root/django/utils
diff options
context:
space:
mode:
authorRussell Keith-Magee <russell@keith-magee.com>2010-03-27 15:54:31 +0000
committerRussell Keith-Magee <russell@keith-magee.com>2010-03-27 15:54:31 +0000
commitad5afd6ed220ed50a2b48d7ccf9786ac0e52f807 (patch)
tree14caa228c595f66afdaa130c1d2fe2db238ee312 /django/utils
parentb31b2d4da3772463d007c9d986c4bdd1392b09e7 (diff)
Fixed #12769, #12924 -- Corrected the pickling of curried and lazy objects, which was preventing queries with translated or related fields from being pickled. And lo, Alex Gaynor didst slayeth the dragon.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@12866 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/utils')
-rw-r--r--django/utils/functional.py9
-rw-r--r--django/utils/translation/__init__.py34
2 files changed, 23 insertions, 20 deletions
diff --git a/django/utils/functional.py b/django/utils/functional.py
index e52ab76a38..b66fdd3012 100644
--- a/django/utils/functional.py
+++ b/django/utils/functional.py
@@ -147,6 +147,12 @@ 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):
"""
Encapsulate a function call and act as a proxy for methods that are
@@ -162,6 +168,9 @@ 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 __prepare_class__(cls):
cls.__dispatch = {}
for resultclass in resultclasses:
diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py
index c0a0df9532..54fb86d499 100644
--- a/django/utils/translation/__init__.py
+++ b/django/utils/translation/__init__.py
@@ -1,8 +1,11 @@
"""
Internationalization support.
"""
-from django.utils.functional import lazy
+from django.conf import settings
from django.utils.encoding import force_unicode
+from django.utils.functional import lazy, curry
+from django.utils.translation import trans_real, trans_null
+
__all__ = ['gettext', 'gettext_noop', 'gettext_lazy', 'ngettext',
'ngettext_lazy', 'string_concat', 'activate', 'deactivate',
@@ -19,32 +22,23 @@ __all__ = ['gettext', 'gettext_noop', 'gettext_lazy', 'ngettext',
# replace the functions with their real counterparts (once we do access the
# settings).
-def delayed_loader(*args, **kwargs):
+def delayed_loader(real_name, *args, **kwargs):
"""
- Replace each real_* function with the corresponding function from either
- trans_real or trans_null (e.g. real_gettext is replaced with
- trans_real.gettext or trans_null.gettext). This function is run once, the
- first time any i18n method is called. It replaces all the i18n methods at
- once at that time.
+ Call the real, underlying function. We have a level of indirection here so
+ that modules can use the translation bits without actually requiring
+ Django's settings bits to be configured before import.
"""
- import traceback
- from django.conf import settings
if settings.USE_I18N:
- import trans_real as trans
+ trans = trans_real
else:
- import trans_null as trans
- caller = traceback.extract_stack(limit=2)[0][2]
- g = globals()
- for name in __all__:
- if hasattr(trans, name):
- g['real_%s' % name] = getattr(trans, name)
+ trans = trans_null
# Make the originally requested function call on the way out the door.
- return g['real_%s' % caller](*args, **kwargs)
+ return getattr(trans, real_name)(*args, **kwargs)
g = globals()
for name in __all__:
- g['real_%s' % name] = delayed_loader
+ g['real_%s' % name] = curry(delayed_loader, name)
del g, delayed_loader
def gettext_noop(message):
@@ -102,10 +96,10 @@ def templatize(src):
def deactivate_all():
return real_deactivate_all()
-def string_concat(*strings):
+def _string_concat(*strings):
"""
Lazy variant of string concatenation, needed for translations that are
constructed from multiple parts.
"""
return u''.join([force_unicode(s) for s in strings])
-string_concat = lazy(string_concat, unicode)
+string_concat = lazy(_string_concat, unicode)