mirror of
				https://github.com/django/django.git
				synced 2025-11-03 21:25:09 +00:00 
			
		
		
		
	Fixed #12060 - equality tests between User and SimpleLazyObject-wrapped User failed.
Also added more tests for SimpleLazyObject Thanks to ericholscher for report. git-svn-id: http://code.djangoproject.com/svn/django/trunk@11637 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		
							parent
							
								
									c6e8e5d9f0
								
							
						
					
					
						commit
						162fade2b7
					
				
					 3 changed files with 109 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -316,14 +316,35 @@ class SimpleLazyObject(LazyObject):
 | 
			
		|||
        if self._wrapped is None: self._setup()
 | 
			
		||||
        return str(self._wrapped)
 | 
			
		||||
 | 
			
		||||
    def __unicode__(self):
 | 
			
		||||
        if self._wrapped is None: self._setup()
 | 
			
		||||
        return unicode(self._wrapped)
 | 
			
		||||
 | 
			
		||||
    def __deepcopy__(self, memo):
 | 
			
		||||
        if self._wrapped is None:
 | 
			
		||||
            result = self.__class__(self._setupfunc)
 | 
			
		||||
            # We have to use SimpleLazyObject, not self.__class__, because the
 | 
			
		||||
            # latter is proxied.
 | 
			
		||||
            result = SimpleLazyObject(self._setupfunc)
 | 
			
		||||
            memo[id(self)] = result
 | 
			
		||||
            return result
 | 
			
		||||
        else:
 | 
			
		||||
            import copy
 | 
			
		||||
            return copy.deepcopy(self._wrapped, memo)
 | 
			
		||||
 | 
			
		||||
    # Need to pretend to be the wrapped class, for the sake of objects that care
 | 
			
		||||
    # about this (especially in equality tests)
 | 
			
		||||
    def __get_class(self):
 | 
			
		||||
        if self._wrapped is None: self._setup()
 | 
			
		||||
        return self._wrapped.__class__
 | 
			
		||||
    __class__ = property(__get_class)
 | 
			
		||||
 | 
			
		||||
    def __eq__(self, other):
 | 
			
		||||
        if self._wrapped is None: self._setup()
 | 
			
		||||
        return self._wrapped == other
 | 
			
		||||
 | 
			
		||||
    def __hash__(self):
 | 
			
		||||
        if self._wrapped is None: self._setup()
 | 
			
		||||
        return hash(self._wrapped)
 | 
			
		||||
 | 
			
		||||
    def _setup(self):
 | 
			
		||||
        self._wrapped = self._setupfunc()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@ Tests for Django's bundled context processors.
 | 
			
		|||
"""
 | 
			
		||||
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.contrib.auth.models import Group
 | 
			
		||||
from django.contrib.auth import authenticate
 | 
			
		||||
from django.db.models import Q
 | 
			
		||||
from django.test import TestCase
 | 
			
		||||
from django.template import Template
 | 
			
		||||
| 
						 | 
				
			
			@ -74,9 +74,13 @@ class AuthContextProcessorTests(TestCase):
 | 
			
		|||
 | 
			
		||||
    def test_user_attrs(self):
 | 
			
		||||
        """
 | 
			
		||||
        Test that ContextLazyObject wraps objects properly
 | 
			
		||||
        Test that the lazy objects returned behave just like the wrapped objects.
 | 
			
		||||
        """
 | 
			
		||||
        # These are 'functional' level tests for common use cases.  Direct
 | 
			
		||||
        # testing of the implementation (SimpleLazyObject) is in the 'utils'
 | 
			
		||||
        # tests.
 | 
			
		||||
        self.client.login(username='super', password='secret')
 | 
			
		||||
        user = authenticate(username='super', password='secret')
 | 
			
		||||
        response = self.client.get('/auth_processor_user/')
 | 
			
		||||
        self.assertContains(response, "unicode: super")
 | 
			
		||||
        self.assertContains(response, "id: 100")
 | 
			
		||||
| 
						 | 
				
			
			@ -100,3 +104,9 @@ class AuthContextProcessorTests(TestCase):
 | 
			
		|||
        #    calling a Python object' in <type 'exceptions.AttributeError'>
 | 
			
		||||
        #    ignored"
 | 
			
		||||
        query = Q(user=response.context['user']) & Q(someflag=True)
 | 
			
		||||
 | 
			
		||||
        # Tests for user equality.  This is hard because User defines
 | 
			
		||||
        # equality in a non-duck-typing way
 | 
			
		||||
        # See bug #12060
 | 
			
		||||
        self.assertEqual(response.context['user'], user)
 | 
			
		||||
        self.assertEqual(user, response.context['user'])
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ Tests for django.utils.
 | 
			
		|||
from unittest import TestCase
 | 
			
		||||
 | 
			
		||||
from django.utils import html, checksums
 | 
			
		||||
from django.utils.functional import SimpleLazyObject
 | 
			
		||||
 | 
			
		||||
import timesince
 | 
			
		||||
import datastructures
 | 
			
		||||
| 
						 | 
				
			
			@ -161,6 +162,80 @@ class TestUtilsChecksums(TestCase):
 | 
			
		|||
        for value, output in items:
 | 
			
		||||
            self.check_output(f, value, output)
 | 
			
		||||
 | 
			
		||||
class _ComplexObject(object):
 | 
			
		||||
    def __init__(self, name):
 | 
			
		||||
        self.name = name
 | 
			
		||||
 | 
			
		||||
    def __eq__(self, other):
 | 
			
		||||
        return self.name == other.name
 | 
			
		||||
 | 
			
		||||
    def __hash__(self):
 | 
			
		||||
        return hash(self.name)
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return "I am _ComplexObject(%r)" % self.name
 | 
			
		||||
 | 
			
		||||
    def __unicode__(self):
 | 
			
		||||
        return unicode(self.name)
 | 
			
		||||
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        return "_ComplexObject(%r)" % self.name
 | 
			
		||||
 | 
			
		||||
complex_object = lambda: _ComplexObject("joe")
 | 
			
		||||
 | 
			
		||||
class TestUtilsSimpleLazyObject(TestCase):
 | 
			
		||||
    """
 | 
			
		||||
    Tests for SimpleLazyObject
 | 
			
		||||
    """
 | 
			
		||||
    # Note that concrete use cases for SimpleLazyObject are also found in the
 | 
			
		||||
    # auth context processor tests (unless the implementation of that function
 | 
			
		||||
    # is changed).
 | 
			
		||||
 | 
			
		||||
    def test_equality(self):
 | 
			
		||||
        self.assertEqual(complex_object(), SimpleLazyObject(complex_object))
 | 
			
		||||
        self.assertEqual(SimpleLazyObject(complex_object), complex_object())
 | 
			
		||||
 | 
			
		||||
    def test_hash(self):
 | 
			
		||||
        # hash() equality would not be true for many objects, but it should be
 | 
			
		||||
        # for _ComplexObject
 | 
			
		||||
        self.assertEqual(hash(complex_object()),
 | 
			
		||||
                         hash(SimpleLazyObject(complex_object)))
 | 
			
		||||
 | 
			
		||||
    def test_repr(self):
 | 
			
		||||
        # For debugging, it will really confuse things if there is no clue that
 | 
			
		||||
        # SimpleLazyObject is actually a proxy object. So we don't
 | 
			
		||||
        # proxy __repr__
 | 
			
		||||
        self.assert_("SimpleLazyObject" in repr(SimpleLazyObject(complex_object)))
 | 
			
		||||
 | 
			
		||||
    def test_str(self):
 | 
			
		||||
        self.assertEqual("I am _ComplexObject('joe')", str(SimpleLazyObject(complex_object)))
 | 
			
		||||
 | 
			
		||||
    def test_unicode(self):
 | 
			
		||||
        self.assertEqual(u"joe", unicode(SimpleLazyObject(complex_object)))
 | 
			
		||||
 | 
			
		||||
    def test_class(self):
 | 
			
		||||
        # This is important for classes that use __class__ in things like
 | 
			
		||||
        # equality tests.
 | 
			
		||||
        self.assertEqual(_ComplexObject, SimpleLazyObject(complex_object).__class__)
 | 
			
		||||
 | 
			
		||||
    def test_deepcopy(self):
 | 
			
		||||
        import copy
 | 
			
		||||
        # Check that we *can* do deep copy, and that it returns the right
 | 
			
		||||
        # objects.
 | 
			
		||||
 | 
			
		||||
        # First, for an unevaluated SimpleLazyObject
 | 
			
		||||
        s = SimpleLazyObject(complex_object)
 | 
			
		||||
        assert s._wrapped is None
 | 
			
		||||
        s2 = copy.deepcopy(s)
 | 
			
		||||
        assert s._wrapped is None # something has gone wrong is s is evaluated
 | 
			
		||||
        self.assertEqual(s2, complex_object())
 | 
			
		||||
 | 
			
		||||
        # Second, for an evaluated SimpleLazyObject
 | 
			
		||||
        name = s.name # evaluate
 | 
			
		||||
        assert s._wrapped is not None
 | 
			
		||||
        s3 = copy.deepcopy(s)
 | 
			
		||||
        self.assertEqual(s3, complex_object())
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    import doctest
 | 
			
		||||
    doctest.testmod()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue