summary refs log tree commit diff
diff options
context:
space:
mode:
authorErik Johnston <erik@matrix.org>2020-01-22 15:39:21 +0000
committerErik Johnston <erik@matrix.org>2020-01-22 15:39:21 +0000
commitb143e6c68869348d937bc022a7e8f102bfde2dd5 (patch)
treea06a91c1a03fe696b3e74cda30136969ecd52d69
parentRefactor HomeServer object to work with type hints (diff)
downloadsynapse-github/erikj/synapse_server_refactor.tar.xz
-rw-r--r--synapse/server.py57
1 files changed, 23 insertions, 34 deletions
diff --git a/synapse/server.py b/synapse/server.py
index 5a0ec4059e..c389739594 100644
--- a/synapse/server.py
+++ b/synapse/server.py
@@ -113,48 +113,37 @@ FuncType = Callable[..., Any]
 F = TypeVar("F", bound=FuncType)
 
 
-class _InjectionDescriptor(object):
-    """A decorator for HomeServer class to implement dependency injection, i.e.
-    caching built classes and detecting cyclic dependencies.
+def builder(f: F) -> F:
+    """Decorator to wrap a HomeServer method to cache result and detect
+    cyclical dependencies.
     """
+    if not f.__name__.startswith("get_"):
+        raise Exception("Function must be named `get_*`")
 
-    def __init__(self, f: F):
-        self.f = f
-
-        if not f.__name__.startswith("get_"):
-            raise Exception("Function must be named `get_*`")
-
-        self.depname = self.f.__name__[len("get_") :]  # type: str
-
-    def __get__(self, obj, objtype=None):
-        @wraps(self.f)
-        def build():
-            try:
-                return getattr(obj, self.depname)
-            except AttributeError:
-                pass
+    depname = f.__name__[len("get_") :]  # type: str
 
-            # Prevent cyclic dependencies from deadlocking
-            if self.depname in obj._building:
-                raise ValueError(
-                    "Cyclic dependency while building %s" % (self.depname,)
-                )
-            obj._building[self.depname] = True
+    @wraps(f)
+    def _get(self):
+        try:
+            return getattr(self, depname)
+        except AttributeError:
+            pass
 
-            dep = self.f(obj)
+        # Prevent cyclic dependencies from deadlocking
+        if depname in self._building:
+            raise ValueError("Cyclic dependency while building %s" % (depname,))
 
-            setattr(obj, self.depname, dep)
+        try:
+            self._building[depname] = True
+            dep = f(self)
+        finally:
+            self._building.pop(depname, None)
 
-            return dep
+        setattr(self, self.depname, dep)
 
-        return build
+        return dep
 
-
-def builder(f: F) -> F:
-    """Decorator to wrap a HomeServer method to cache result and detect
-    cyclical dependencies.
-    """
-    return cast(F, _InjectionDescriptor(f))
+    return cast(F, _get)
 
 
 class HomeServer(object):