2 from django.utils.functional import empty, LazyObject, SimpleLazyObject
4 # Supply LazyObject and SimpleLazyObject for django < r16308
9 def new_method_proxy(func):
10 def inner(self, *args):
11 if self._wrapped is empty:
13 return func(self._wrapped, *args)
16 class LazyObject(object):
18 A wrapper for another class that can be used to delay instantiation of the
21 By subclassing, you have the opportunity to intercept and alter the
22 instantiation. If you don't need to do that, use SimpleLazyObject.
27 __getattr__ = new_method_proxy(getattr)
29 def __setattr__(self, name, value):
30 if name == "_wrapped":
31 # Assign to __dict__ to avoid infinite __setattr__ loops.
32 self.__dict__["_wrapped"] = value
34 if self._wrapped is empty:
36 setattr(self._wrapped, name, value)
38 def __delattr__(self, name):
39 if name == "_wrapped":
40 raise TypeError("can't delete _wrapped.")
41 if self._wrapped is empty:
43 delattr(self._wrapped, name)
47 Must be implemented by subclasses to initialise the wrapped object.
49 raise NotImplementedError
51 # introspection support:
52 __members__ = property(lambda self: self.__dir__())
53 __dir__ = new_method_proxy(dir)
56 class SimpleLazyObject(LazyObject):
58 A lazy object initialised from any function.
60 Designed for compound objects of unknown type. For builtins or objects of
61 known type, use django.utils.functional.lazy.
63 def __init__(self, func):
65 Pass in a callable that returns the object to be wrapped.
67 If copies are made of the resulting SimpleLazyObject, which can happen
68 in various circumstances within Django, then you must ensure that the
69 callable can be safely run more than once and will return the same
72 self.__dict__['_setupfunc'] = func
73 super(SimpleLazyObject, self).__init__()
76 self._wrapped = self._setupfunc()
78 __str__ = new_method_proxy(str)
79 __unicode__ = new_method_proxy(unicode)
81 def __deepcopy__(self, memo):
82 if self._wrapped is empty:
83 # We have to use SimpleLazyObject, not self.__class__, because the
85 result = SimpleLazyObject(self._setupfunc)
86 memo[id(self)] = result
90 return copy.deepcopy(self._wrapped, memo)
92 # Need to pretend to be the wrapped class, for the sake of objects that care
93 # about this (especially in equality tests)
94 __class__ = property(new_method_proxy(operator.attrgetter("__class__")))
95 __eq__ = new_method_proxy(operator.eq)
96 __hash__ = new_method_proxy(hash)
97 __nonzero__ = new_method_proxy(bool)