Commit 22be3d76 authored by Luke Plant's avatar Luke Plant
Browse files

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
parent cb7a3262
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -297,6 +297,11 @@ class SimpleLazyObject(LazyObject):
    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 @@ class SimpleLazyObject(LazyObject):
        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()
+19 −0
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@ Tests for Django's bundled context processors.
"""

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 @@ class AuthContextProcessorTests(TestCase):
        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)