Author: lukeplant
Date: 2009-10-19 16:17:33 -0500 (Mon, 19 Oct 2009)
New Revision: 11635
Modified:
django/branches/releases/1.1.X/
django/branches/releases/1.1.X/django/utils/functional.py
django/branches/releases/1.1.X/tests/regressiontests/context_processors/tests.py
Log:
[1.1.X] Fixed #12049 - LazyObject-wrapped User breaks queries in template tags
Thanks to chipx86 for the report and patch.
Backport of r11634 from trunk
Property changes on: django/branches/releases/1.1.X
___________________________________________________________________
Name: svnmerge-integrated
-
/django/trunk:1-11500,11523,11527-11528,11531-11552,11554,11577,11579-11581,11596,11623,11625
+
/django/trunk:1-11500,11523,11527-11528,11531-11552,11554,11577,11579-11581,11596,11623,11625,11634
Modified: django/branches/releases/1.1.X/django/utils/functional.py
===================================================================
--- django/branches/releases/1.1.X/django/utils/functional.py 2009-10-19
21:13:22 UTC (rev 11634)
+++ django/branches/releases/1.1.X/django/utils/functional.py 2009-10-19
21:17:33 UTC (rev 11635)
@@ -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/branches/releases/1.1.X/tests/regressiontests/context_processors/tests.py
===================================================================
---
django/branches/releases/1.1.X/tests/regressiontests/context_processors/tests.py
2009-10-19 21:13:22 UTC (rev 11634)
+++
django/branches/releases/1.1.X/tests/regressiontests/context_processors/tests.py
2009-10-19 21:17:33 UTC (rev 11635)
@@ -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
-~----------~----~----~----~------~----~------~--~---