123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- from __future__ import unicode_literals
- import copy
- import pickle
- import sys
- from unittest import TestCase
- from django.utils import six
- from django.utils.functional import LazyObject, SimpleLazyObject, empty
- class Foo(object):
- """
- A simple class with just one attribute.
- """
- foo = 'bar'
- def __eq__(self, other):
- return self.foo == other.foo
- class LazyObjectTestCase(TestCase):
- def lazy_wrap(self, wrapped_object):
- """
- Wrap the given object into a LazyObject
- """
- class AdHocLazyObject(LazyObject):
- def _setup(self):
- self._wrapped = wrapped_object
- return AdHocLazyObject()
- def test_getattr(self):
- obj = self.lazy_wrap(Foo())
- self.assertEqual(obj.foo, 'bar')
- def test_setattr(self):
- obj = self.lazy_wrap(Foo())
- obj.foo = 'BAR'
- obj.bar = 'baz'
- self.assertEqual(obj.foo, 'BAR')
- self.assertEqual(obj.bar, 'baz')
- def test_setattr2(self):
- # Same as test_setattr but in reversed order
- obj = self.lazy_wrap(Foo())
- obj.bar = 'baz'
- obj.foo = 'BAR'
- self.assertEqual(obj.foo, 'BAR')
- self.assertEqual(obj.bar, 'baz')
- def test_delattr(self):
- obj = self.lazy_wrap(Foo())
- obj.bar = 'baz'
- self.assertEqual(obj.bar, 'baz')
- del obj.bar
- with self.assertRaises(AttributeError):
- obj.bar
- def test_cmp(self):
- obj1 = self.lazy_wrap('foo')
- obj2 = self.lazy_wrap('bar')
- obj3 = self.lazy_wrap('foo')
- self.assertEqual(obj1, 'foo')
- self.assertEqual(obj1, obj3)
- self.assertNotEqual(obj1, obj2)
- self.assertNotEqual(obj1, 'bar')
- def test_bytes(self):
- obj = self.lazy_wrap(b'foo')
- self.assertEqual(bytes(obj), b'foo')
- def test_text(self):
- obj = self.lazy_wrap('foo')
- self.assertEqual(six.text_type(obj), 'foo')
- def test_bool(self):
- # Refs #21840
- for f in [False, 0, (), {}, [], None, set()]:
- self.assertFalse(self.lazy_wrap(f))
- for t in [True, 1, (1,), {1: 2}, [1], object(), {1}]:
- self.assertTrue(t)
- def test_dir(self):
- obj = self.lazy_wrap('foo')
- self.assertEqual(dir(obj), dir('foo'))
- def test_len(self):
- for seq in ['asd', [1, 2, 3], {'a': 1, 'b': 2, 'c': 3}]:
- obj = self.lazy_wrap(seq)
- self.assertEqual(len(obj), 3)
- def test_class(self):
- self.assertIsInstance(self.lazy_wrap(42), int)
- class Bar(Foo):
- pass
- self.assertIsInstance(self.lazy_wrap(Bar()), Foo)
- def test_hash(self):
- obj = self.lazy_wrap('foo')
- d = {}
- d[obj] = 'bar'
- self.assertIn('foo', d)
- self.assertEqual(d['foo'], 'bar')
- def test_contains(self):
- test_data = [
- ('c', 'abcde'),
- (2, [1, 2, 3]),
- ('a', {'a': 1, 'b': 2, 'c': 3}),
- (2, {1, 2, 3}),
- ]
- for needle, haystack in test_data:
- self.assertIn(needle, self.lazy_wrap(haystack))
- # __contains__ doesn't work when the haystack is a string and the needle a LazyObject
- for needle_haystack in test_data[1:]:
- self.assertIn(self.lazy_wrap(needle), haystack)
- self.assertIn(self.lazy_wrap(needle), self.lazy_wrap(haystack))
- def test_getitem(self):
- obj_list = self.lazy_wrap([1, 2, 3])
- obj_dict = self.lazy_wrap({'a': 1, 'b': 2, 'c': 3})
- self.assertEqual(obj_list[0], 1)
- self.assertEqual(obj_list[-1], 3)
- self.assertEqual(obj_list[1:2], [2])
- self.assertEqual(obj_dict['b'], 2)
- with self.assertRaises(IndexError):
- obj_list[3]
- with self.assertRaises(KeyError):
- obj_dict['f']
- def test_setitem(self):
- obj_list = self.lazy_wrap([1, 2, 3])
- obj_dict = self.lazy_wrap({'a': 1, 'b': 2, 'c': 3})
- obj_list[0] = 100
- self.assertEqual(obj_list, [100, 2, 3])
- obj_list[1:2] = [200, 300, 400]
- self.assertEqual(obj_list, [100, 200, 300, 400, 3])
- obj_dict['a'] = 100
- obj_dict['d'] = 400
- self.assertEqual(obj_dict, {'a': 100, 'b': 2, 'c': 3, 'd': 400})
- def test_delitem(self):
- obj_list = self.lazy_wrap([1, 2, 3])
- obj_dict = self.lazy_wrap({'a': 1, 'b': 2, 'c': 3})
- del obj_list[-1]
- del obj_dict['c']
- self.assertEqual(obj_list, [1, 2])
- self.assertEqual(obj_dict, {'a': 1, 'b': 2})
- with self.assertRaises(IndexError):
- del obj_list[3]
- with self.assertRaises(KeyError):
- del obj_dict['f']
- def test_iter(self):
- # LazyObjects don't actually implements __iter__ but you can still
- # iterate over them because they implement __getitem__
- obj = self.lazy_wrap([1, 2, 3])
- for expected, actual in zip([1, 2, 3], obj):
- self.assertEqual(expected, actual)
- def test_pickle(self):
- # See ticket #16563
- obj = self.lazy_wrap(Foo())
- pickled = pickle.dumps(obj)
- unpickled = pickle.loads(pickled)
- self.assertIsInstance(unpickled, Foo)
- self.assertEqual(unpickled, obj)
- self.assertEqual(unpickled.foo, obj.foo)
- def test_deepcopy(self):
- # Check that we *can* do deep copy, and that it returns the right
- # objects.
- l = [1, 2, 3]
- obj = self.lazy_wrap(l)
- len(l) # forces evaluation
- obj2 = copy.deepcopy(obj)
- self.assertIsInstance(obj2, list)
- self.assertEqual(obj2, [1, 2, 3])
- def test_deepcopy_no_evaluation(self):
- # copying doesn't force evaluation
- l = [1, 2, 3]
- obj = self.lazy_wrap(l)
- obj2 = copy.deepcopy(obj)
- # Copying shouldn't force evaluation
- self.assertIs(obj._wrapped, empty)
- self.assertIs(obj2._wrapped, empty)
- class SimpleLazyObjectTestCase(LazyObjectTestCase):
- # By inheriting from LazyObjectTestCase and redefining the lazy_wrap()
- # method which all testcases use, we get to make sure all behaviors
- # tested in the parent testcase also apply to SimpleLazyObject.
- def lazy_wrap(self, wrapped_object):
- return SimpleLazyObject(lambda: wrapped_object)
- def test_repr(self):
- # First, for an unevaluated SimpleLazyObject
- obj = self.lazy_wrap(42)
- # __repr__ contains __repr__ of setup function and does not evaluate
- # the SimpleLazyObject
- six.assertRegex(self, repr(obj), '^<SimpleLazyObject:')
- self.assertIs(obj._wrapped, empty) # make sure evaluation hasn't been triggered
- self.assertEqual(obj, 42) # evaluate the lazy object
- self.assertIsInstance(obj._wrapped, int)
- self.assertEqual(repr(obj), '<SimpleLazyObject: 42>')
- def test_trace(self):
- # See ticket #19456
- old_trace_func = sys.gettrace()
- try:
- def trace_func(frame, event, arg):
- frame.f_locals['self'].__class__
- if old_trace_func is not None:
- old_trace_func(frame, event, arg)
- sys.settrace(trace_func)
- self.lazy_wrap(None)
- finally:
- sys.settrace(old_trace_func)
- def test_none(self):
- i = [0]
- def f():
- i[0] += 1
- return None
- x = SimpleLazyObject(f)
- self.assertEqual(str(x), "None")
- self.assertEqual(i, [1])
- self.assertEqual(str(x), "None")
- self.assertEqual(i, [1])
- def test_dict(self):
- # See ticket #18447
- lazydict = SimpleLazyObject(lambda: {'one': 1})
- self.assertEqual(lazydict['one'], 1)
- lazydict['one'] = -1
- self.assertEqual(lazydict['one'], -1)
- self.assertTrue('one' in lazydict)
- self.assertFalse('two' in lazydict)
- self.assertEqual(len(lazydict), 1)
- del lazydict['one']
- with self.assertRaises(KeyError):
- lazydict['one']
- def test_list_set(self):
- lazy_list = SimpleLazyObject(lambda: [1, 2, 3, 4, 5])
- lazy_set = SimpleLazyObject(lambda: {1, 2, 3, 4})
- self.assertTrue(1 in lazy_list)
- self.assertTrue(1 in lazy_set)
- self.assertFalse(6 in lazy_list)
- self.assertFalse(6 in lazy_set)
- self.assertEqual(len(lazy_list), 5)
- self.assertEqual(len(lazy_set), 4)
|