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
-~----------~----~----~----~------~----~------~--~---

Reply via email to