Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #12049 - LazyObject-wrapped User breaks queries in template tags

Thanks to chipx86 for the report and patch.



git-svn-id: http://code.djangoproject.com/svn/django/trunk@11634 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 22be3d7612b518268b84ce37d3b20f828efb4b6f 1 parent cb7a326
Luke Plant authored October 19, 2009
14  django/utils/functional.py
@@ -297,6 +297,11 @@ class SimpleLazyObject(LazyObject):
297 297
     def __init__(self, func):
298 298
         """
299 299
         Pass in a callable that returns the object to be wrapped.
  300
+
  301
+        If copies are made of the resulting SimpleLazyObject, which can happen
  302
+        in various circumstances within Django, then you must ensure that the
  303
+        callable can be safely run more than once and will return the same
  304
+        value.
300 305
         """
301 306
         self.__dict__['_setupfunc'] = func
302 307
         # For some reason, we have to inline LazyObject.__init__ here to avoid
@@ -307,5 +312,14 @@ def __str__(self):
307 312
         if self._wrapped is None: self._setup()
308 313
         return str(self._wrapped)
309 314
 
  315
+    def __deepcopy__(self, memo):
  316
+        if self._wrapped is None:
  317
+            result = self.__class__(self._setupfunc)
  318
+            memo[id(self)] = result
  319
+            return result
  320
+        else:
  321
+            import copy
  322
+            return copy.deepcopy(self._wrapped, memo)
  323
+
310 324
     def _setup(self):
311 325
         self._wrapped = self._setupfunc()
19  tests/regressiontests/context_processors/tests.py
@@ -3,6 +3,8 @@
3 3
 """
4 4
 
5 5
 from django.conf import settings
  6
+from django.contrib.auth.models import Group
  7
+from django.db.models import Q
6 8
 from django.test import TestCase
7 9
 from django.template import Template
8 10
 
@@ -81,3 +83,20 @@ def test_user_attrs(self):
81 83
         self.assertContains(response, "username: super")
82 84
         # bug #12037 is tested by the {% url %} in the template:
83 85
         self.assertContains(response, "url: /userpage/super/")
  86
+
  87
+        # See if this object can be used for queries where a Q() comparing
  88
+        # a user can be used with another Q() (in an AND or OR fashion).
  89
+        # This simulates what a template tag might do with the user from the
  90
+        # context. Note that we don't need to execute a query, just build it.
  91
+        #
  92
+        # The failure case (bug #12049) on Python 2.4 with a LazyObject-wrapped
  93
+        # User is a fatal TypeError: "function() takes at least 2 arguments
  94
+        # (0 given)" deep inside deepcopy().
  95
+        #
  96
+        # Python 2.5 and 2.6 succeeded, but logged internally caught exception
  97
+        # spew:
  98
+        #
  99
+        #    Exception RuntimeError: 'maximum recursion depth exceeded while
  100
+        #    calling a Python object' in <type 'exceptions.AttributeError'>
  101
+        #    ignored"
  102
+        query = Q(user=response.context['user']) & Q(someflag=True)

0 notes on commit 22be3d7

Please sign in to comment.
Something went wrong with that request. Please try again.