Author: lukeplant
Date: 2009-10-19 16:13:22 -0500 (Mon, 19 Oct 2009)
New Revision: 11634
Modified:
django/trunk/django/utils/functional.py
django/trunk/tests/regressiontests/context_processors/tests.py
Log:
Fixed #12049 - LazyObject-wrapped User breaks queries in template tags
Thanks to chipx86 for the report and patch.
Modified: django/trunk/django/utils/functional.py
===================================================================
--- django/trunk/django/utils/functional.py 2009-10-19 19:21:08 UTC (rev
11633)
+++ django/trunk/django/utils/functional.py 2009-10-19 21:13:22 UTC (rev
11634)
@@ -297,6 +297,11 @@
def __init__(self, func):
"""
Pass in a callable that returns the object to be wrapped.
+
+ If copies are made of the resulting SimpleLazyObject, which can happen
+ in various circumstances within Django, then you must ensure that the
+ callable can be safely run more than once and will return the same
+ value.
"""
self.__dict__['_setupfunc'] = func
# For some reason, we have to inline LazyObject.__init__ here to avoid
@@ -307,5 +312,14 @@
if self._wrapped is None: self._setup()
return str(self._wrapped)
+ def __deepcopy__(self, memo):
+ if self._wrapped is None:
+ result = self.__class__(self._setupfunc)
+ memo[id(self)] = result
+ return result
+ else:
+ import copy
+ return copy.deepcopy(self._wrapped, memo)
+
def _setup(self):
self._wrapped = self._setupfunc()
Modified: django/trunk/tests/regressiontests/context_processors/tests.py
===================================================================
--- django/trunk/tests/regressiontests/context_processors/tests.py
2009-10-19 19:21:08 UTC (rev 11633)
+++ django/trunk/tests/regressiontests/context_processors/tests.py
2009-10-19 21:13:22 UTC (rev 11634)
@@ -3,6 +3,8 @@
"""
from django.conf import settings
+from django.contrib.auth.models import Group
+from django.db.models import Q
from django.test import TestCase
from django.template import Template
@@ -81,3 +83,20 @@
self.assertContains(response, "username: super")
# bug #12037 is tested by the {% url %} in the template:
self.assertContains(response, "url: /userpage/super/")
+
+ # See if this object can be used for queries where a Q() comparing
+ # a user can be used with another Q() (in an AND or OR fashion).
+ # This simulates what a template tag might do with the user from the
+ # context. Note that we don't need to execute a query, just build it.
+ #
+ # The failure case (bug #12049) on Python 2.4 with a LazyObject-wrapped
+ # User is a fatal TypeError: "function() takes at least 2 arguments
+ # (0 given)" deep inside deepcopy().
+ #
+ # Python 2.5 and 2.6 succeeded, but logged internally caught exception
+ # spew:
+ #
+ # Exception RuntimeError: 'maximum recursion depth exceeded while
+ # calling a Python object' in <type 'exceptions.AttributeError'>
+ # ignored"
+ query = Q(user=response.context['user']) & Q(someflag=True)
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---