Plugin classes instead of modules
authorBenjamin Braatz <benjamin.braatz@graph-it.com>
Wed, 24 Feb 2021 14:08:10 +0000 (15:08 +0100)
committerBenjamin Braatz <benjamin.braatz@graph-it.com>
Wed, 24 Feb 2021 14:09:03 +0000 (15:09 +0100)
conf.json
controlpi/main.py
controlpi/plugins/alias.py
controlpi/plugins/delay.py
controlpi/plugins/init.py
controlpi/plugins/log.py
controlpi/plugins/plugin.py [new file with mode: 0644]

index 18eeee593af47bea5f21b96293ec26793868d93b..02fef2a6d8e9d38a5c50302cc8bb148a20101cfa 100644 (file)
--- a/conf.json
+++ b/conf.json
@@ -1,9 +1,4 @@
-{ "delay":
-  [ { "name": "D1",
-      "seconds": 1.0 },
-    { "name": "D2",
-      "seconds": 2.0 } ],
-  "alias":
+{ "Alias":
   [ { "name": "One-second delay",
       "aliasfor":
       { "name": "D1" } },
       "aliasfor":
       { "name": "D2",
         "event": "finished" } } ],
-  "log":
-  [ { "name": "Debug Logger",
-      "filter": {} },
-    { "name": "Test Logger",
-      "filter": { "name": "Test" } } ],
-  "init":
+  "Delay":
+  [ { "name": "D1",
+      "seconds": 1.0 },
+    { "name": "D2",
+      "seconds": 2.0 } ],
+  "Init":
   [ { "name": "Test Procedure",
-      "commands":
+      "messages":
       [ { "name": "Test", "event": "started" },
         { "name": "D1", "command": "start" },
         { "name": "D2", "command": "start" },
         { "name": "D1", "command": "start" },
         { "name": "D2", "command": "start" },
-        { "name": "Test", "event": "stopped" } ] } ] }
+        { "name": "Test", "event": "stopped" } ] } ],
+  "Log":
+  [ { "name": "Debug Logger",
+      "filter": {} },
+    { "name": "Test Logger",
+      "filter": { "name": "Test" } } ] }
index 76081c8006986a05f6488aaf84d82913273915b6..11e4bd8380529d16771cf84f2ecc282bad5328e1 100644 (file)
@@ -3,6 +3,7 @@ import json
 import asyncio
 import pkgutil
 import importlib
+import inspect
 
 import controlpi.plugins
 
@@ -65,10 +66,15 @@ class ControlPi:
 
 
 async def main():
-    plugins = {name: importlib.import_module(controlpi.plugins.__name__ +
-                                             '.' + name)
-               for finder, name, ispkg
-               in pkgutil.iter_modules(controlpi.plugins.__path__)}
+    plugins_mod = controlpi.plugins
+    plugins = {}
+    for _, mod_name, _ in pkgutil.iter_modules(plugins_mod.__path__):
+        mod = importlib.import_module(f"{plugins_mod.__name__}.{mod_name}")
+        clses = inspect.getmembers(mod, inspect.isclass)
+        for (_, c) in clses:
+            if (issubclass(c, plugins_mod.plugin.Plugin) and
+                    (c is not plugins_mod.plugin.Plugin)):
+                plugins[c.__name__] = c
     coros = []
     with open(sys.argv[1]) as json_data:
         conf = json.load(json_data)
@@ -76,10 +82,11 @@ async def main():
         coros.append(control_pi.run())
         for plugin_name in conf:
             if plugin_name in plugins:
-                module = plugins[plugin_name]
+                plugin = plugins[plugin_name]
                 plugin_confs = conf[plugin_name]
                 for plugin_conf in plugin_confs:
-                    coros.append(module.init(control_pi, plugin_conf))
+                    instance = plugin(control_pi, plugin_conf)
+                    coros.append(instance.run())
     await asyncio.gather(*coros)
 
 
index 56131e754d997e3607f8f36453229dbc2596faf3..582b2445d0a8f45bdfae9700105b66a4c7c3ac34 100644 (file)
@@ -1,21 +1,14 @@
-import asyncio
-import functools
+from controlpi.plugins.plugin import Plugin
 
 
-async def alias(control_pi, name, aliasfor, message):
-    alias_message = {"name": name}
-    for key in message:
-        if key not in aliasfor:
-            alias_message[key] = message[key]
-    await control_pi.send(alias_message)
+class Alias(Plugin):
+    async def _alias(self, message):
+        alias_message = {"name": self._name}
+        for key in message:
+            if key not in self._aliasfor:
+                alias_message[key] = message[key]
+        await self._control_pi.send(alias_message)
 
-
-async def init_finished(name):
-    print(f"{name} initialised")
-
-
-def init(control_pi, conf):
-    callback = functools.partial(alias, control_pi,
-                                 conf['name'], conf['aliasfor'])
-    control_pi.register(conf['aliasfor'], callback)
-    return init_finished(conf['name'])
+    def _process_conf(self, conf):
+        self._aliasfor = conf['aliasfor']
+        self._control_pi.register(conf['aliasfor'], self._alias)
index 3138b5458c3539004f2d04cfede0f237bebaa304..5efb33ce546f10ec501ddad9e1cd7b0dbd24d744 100644 (file)
@@ -1,18 +1,13 @@
+from controlpi.plugins.plugin import Plugin
 import asyncio
-import functools
 
 
-async def waiter(control_pi, name, seconds, message):
-    await asyncio.sleep(seconds)
-    await control_pi.send({"name": name, "event": "finished"})
+class Delay(Plugin):
+    async def _wait(self, message):
+        await asyncio.sleep(self._seconds)
+        await self._control_pi.send({"name": self._name, "event": "finished"})
 
-
-async def init_finished(name):
-    print(f"{name} initialised")
-
-
-def init(control_pi, conf):
-    callback = functools.partial(waiter, control_pi,
-                                 conf['name'], conf['seconds'])
-    control_pi.register({"name": conf['name'], "command": "start"}, callback)
-    return init_finished(conf['name'])
+    def _process_conf(self, conf):
+        self._seconds = conf['seconds']
+        self._control_pi.register({"name": self._name, "command": "start"},
+                                  self._wait)
index df10a9b1df576e4c9fd7a454f168aeab094181f7..9d9760cb0f448b1e20202f0a273c5e43af03666d 100644 (file)
@@ -1,11 +1,12 @@
+from controlpi.plugins.plugin import Plugin
 import asyncio
 
 
-async def run(control_pi, conf):
-    print(f"{conf['name']} initialised")
-    for message in conf['commands']:
-        await control_pi.send(message)
+class Init(Plugin):
+    async def run(self):
+        print(f"{self._name} initialised")
+        for message in self._messages:
+            await self._control_pi.send(message)
 
-
-def init(control_pi, conf):
-    return run(control_pi, conf)
+    def _process_conf(self, conf):
+        self._messages = conf['messages']
index 7f3aa37fff93e2c74a21283e77bc05b17d426e7c..1d92de16dd97823c9566e0077809d3242efd5517 100644 (file)
@@ -1,15 +1,9 @@
-import functools
+from controlpi.plugins.plugin import Plugin
 
 
-async def logger(name, message):
-    print(f"{name}: {message}")
+class Log(Plugin):
+    async def _log(self, message):
+        print(f"{self._name}: {message}")
 
-
-async def init_finished(name):
-    print(f"{name} initialised")
-
-
-def init(control_pi, conf):
-    callback = functools.partial(logger, conf['name'])
-    control_pi.register(conf['filter'], callback)
-    return init_finished(conf['name'])
+    def _process_conf(self, conf):
+        self._control_pi.register(conf['filter'], self._log)
diff --git a/controlpi/plugins/plugin.py b/controlpi/plugins/plugin.py
new file mode 100644 (file)
index 0000000..b80f9a0
--- /dev/null
@@ -0,0 +1,11 @@
+class Plugin:
+    def __init__(self, control_pi, conf):
+        self._control_pi = control_pi
+        self._name = conf['name']
+        self._process_conf(conf)
+
+    async def run(self):
+        print(f"{self._name} initialised")
+
+    def _process_conf(self, conf):
+        pass