Autocomplete working in query_editor plugin
[unfold.git] / manifold / util / functional.py
diff --git a/manifold/util/functional.py b/manifold/util/functional.py
new file mode 100644 (file)
index 0000000..a411939
--- /dev/null
@@ -0,0 +1,53 @@
+"""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)
+