feat: improve plugin support

This commit is contained in:
0xMRTT 2022-08-16 15:54:40 +02:00
parent f9836e7ef5
commit 88ec3317fc
No known key found for this signature in database
GPG key ID: AC9E06BF3DECB6FB
5 changed files with 146 additions and 2 deletions

View file

@ -16,10 +16,37 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from .setting import AdwcustomizerSetting
#from .setting import AdwcustomizerSetting
from dataclasses import dataclass
from importlib import import_module
import os
import sys
import importlib.util
class AdwcustomizerPluginBase:
@dataclass
class Meta:
name: str
description: str
version: str
def __str__(self) -> str:
return f'{self.name}: {self.version}'
class IPluginRegistry(type):
plugin_registries = list()
def __init__(cls, name, bases, attrs):
super().__init__(cls)
if name != 'AdwcustomizerPluginCore':
IPluginRegistry.plugin_registries.append(cls)
class AdwcustomizerPluginCore(metaclass=IPluginRegistry):
meta: Meta
def __init__(self):
self.title = None
@ -62,3 +89,98 @@ class AdwcustomizerPluginBase:
def save(self):
raise NotImplementedError()
class PluginUseCase:
def __init__(self, directory) -> None:
self.plugins_package = directory
self.modules = []
def __check_loaded_plugin_state(self, plugin_module):
if len(IPluginRegistry.plugin_registries) > 0:
latest_module = IPluginRegistry.plugin_registries[-1]
latest_module_name = latest_module.__module__
current_module_name = plugin_module.__name__
if current_module_name == latest_module_name:
print(f'Successfully imported module `{current_module_name}`')
self.modules.append(latest_module)
else:
print(
f'Expected to import -> `{current_module_name}` but got -> `{latest_module_name}`'
)
# clear plugins from the registry when we're done with them
IPluginRegistry.plugin_registries.clear()
else:
print(f'No plugin found in registry for module: {plugin_module}')
def __search_for_plugins_in(self, plugins_path, package_name):
print(f"plugins path: {plugins_path}")
sys.path.append(plugins_path)
for m in os.listdir(plugins_path):
module = import_module(m)
self.__check_loaded_plugin_state(module)
print(dir(module))
def discover_plugins(self, reload: bool):
"""
Discover the plugin classes contained in Python files, given a
list of directory names to scan.
"""
if reload:
print("Reload")
self.modules.clear()
IPluginRegistry.plugin_registries.clear()
print(
f'Searching for plugins under package {self.plugins_package}')
package_name = os.path.basename(
os.path.normpath(self.plugins_package))
self.__search_for_plugins_in(self.plugins_package, package_name)
@staticmethod
def register_plugin(module: type, logger) -> AdwcustomizerPluginCore:
"""
Create a plugin instance from the given module
:param module: module to initialize
:param logger: logger for the module to use
:return: a high level plugin
"""
return module(logger)
@staticmethod
def hook_plugin(plugin: AdwcustomizerPluginCore):
"""
Return a function accepting commands.
"""
return plugin.invoke
class PluginEngine:
def __init__(self, **args) -> None:
self.use_case = PluginUseCase(os.path.join(
os.environ["HOME"],
".gradience_plugins"))
def start(self) -> None:
self.__reload_plugins()
self.__invoke_on_plugins('Q')
def __reload_plugins(self) -> None:
"""Reset the list of all plugins and initiate the walk over the main
provided plugin package to load all available plugins
"""
self.use_case.discover_plugins(True)
def __invoke_on_plugins(self, command: chr):
"""Apply all of the plugins on the argument supplied to this function
"""
for module in self.use_case.modules:
plugin = self.use_case.register_plugin(module)
delegate = self.use_case.hook_plugin(plugin)
plugin = delegate(command=command)
print(f'Loaded plugin: {plugin}')
if __name__ == "__main__":
engine = PluginEngine()
engine.start()

View file

@ -0,0 +1 @@
from .main import *

10
src/plugins/gdm/main.py Normal file
View file

@ -0,0 +1,10 @@
from adwcustomizer.plugin import AdwcustomizerPluginCore
class GDMPlugin(AdwcustomizerPluginCore):
def validate(self):
print("validate")
def apply(self, dark_theme=False):
print("apply")
def save(self):
print("save")

View file

@ -0,0 +1 @@
from .main import *

10
src/plugins/shell/main.py Normal file
View file

@ -0,0 +1,10 @@
from adwcustomizer.plugin import AdwcustomizerPluginCore
class ShellPlugin(AdwcustomizerPluginCore):
def validate(self):
print("validate")
def apply(self, dark_theme=False):
print("apply")
def save(self):
print("save")