--- /dev/null
+"""Borrowed from Django."""
+
+from threading import Lock
+
+class LazyObject(object):
+ """
+ A wrapper for another class that can be used to delay instantiation of the
+ wrapped class.
+
+ By subclassing, you have the opportunity to intercept and alter the
+ instantiation. If you don't need to do that, use SimpleLazyObject.
+ """
+ def __init__(self):
+ self._wrapped = None
+ self._lock = Lock()
+
+ def __getattr__(self, name):
+ self._lock.acquire()
+ if self._wrapped is None:
+ self._setup()
+ self._lock.release()
+ return getattr(self._wrapped, name)
+
+ def __setattr__(self, name, value):
+ if name in ["_wrapped", "_lock"]:
+ # Assign to __dict__ to avoid infinite __setattr__ loops.
+ self.__dict__[name] = value
+ else:
+ if self._wrapped is None:
+ self._setup()
+ setattr(self._wrapped, name, value)
+
+ def __delattr__(self, name):
+ if name == "_wrapped":
+ raise TypeError("can't delete _wrapped.")
+ if self._wrapped is None:
+ self._setup()
+ delattr(self._wrapped, name)
+
+ def _setup(self):
+ """
+ Must be implemented by subclasses to initialise the wrapped object.
+ """
+ raise NotImplementedError
+
+ # introspection support:
+ __members__ = property(lambda self: self.__dir__())
+
+ def __dir__(self):
+ if self._wrapped is None:
+ self._setup()
+ return dir(self._wrapped)
+