diff --git a/core/cat/mad_hatter/mad_hatter.py b/core/cat/mad_hatter/mad_hatter.py index 8ffe4746..51922a85 100644 --- a/core/cat/mad_hatter/mad_hatter.py +++ b/core/cat/mad_hatter/mad_hatter.py @@ -52,7 +52,7 @@ def install_plugin(self, package_plugin): raise Exception("A plugin should contain a folder, found a file") # create plugin obj - self.load_plugin(plugin_path, active=False) + self.load_plugin(plugin_path) # activate it self.toggle_plugin(plugin_id) @@ -95,21 +95,21 @@ def find_plugins(self): # discover plugins, folder by folder for folder in all_plugin_folders: + self.load_plugin(folder) - # is the plugin active? - folder_base = os.path.basename(os.path.normpath(folder)) - is_active = folder_base in self.active_plugins - - self.load_plugin(folder, is_active) + plugin_id = os.path.basename(os.path.normpath(folder)) + + if plugin_id in self.active_plugins: + self.plugins[plugin_id].activate() self.sync_hooks_and_tools() - def load_plugin(self, plugin_path, active): + def load_plugin(self, plugin_path): # Instantiate plugin. # If the plugin is inactive, only manifest will be loaded # If active, also settings, tools and hooks try: - plugin = Plugin(plugin_path, active=active) + plugin = Plugin(plugin_path) # if plugin is valid, keep a reference self.plugins[plugin.id] = plugin except Exception as e: diff --git a/core/cat/mad_hatter/plugin.py b/core/cat/mad_hatter/plugin.py index dbe508c0..2dfa6f57 100644 --- a/core/cat/mad_hatter/plugin.py +++ b/core/cat/mad_hatter/plugin.py @@ -18,7 +18,7 @@ class Plugin: - def __init__(self, plugin_path: str, active: bool): + def __init__(self, plugin_path: str): # does folder exist? if not os.path.exists(plugin_path) or not os.path.isdir(plugin_path): @@ -45,29 +45,26 @@ def __init__(self, plugin_path: str, active: bool): # but they are created and stored in each plugin instance self._hooks = [] self._tools = [] - self._active = False - # all plugins start active, they can be deactivated/reactivated from endpoint - if active: - self.activate() - def activate(self): # lists of hooks and tools self._hooks, self._tools = self._load_hooks_and_tools() self._active = True def deactivate(self): - self._active = False - # Remove the imported modules for py_file in self.py_files: - py_filename = py_file.replace("/", ".").replace(".py", "") # this is UGLY I know. I'm sorry - log(f"Remove module {py_filename}", "DEBUG") - sys.modules.pop(py_filename) + py_filename = py_file.replace("/", ".").replace(".py", "") + + # If the module is imported it is removed + if py_filename in sys.modules: + log(f"Remove module {py_filename}", "DEBUG") + sys.modules.pop(py_filename) self._hooks = [] self._tools = [] + self._active = False # get plugin settings JSON schema def get_settings_schema(self): diff --git a/core/tests/mad_hatter/test_plugin.py b/core/tests/mad_hatter/test_plugin.py index d2b67d45..4770c4a1 100644 --- a/core/tests/mad_hatter/test_plugin.py +++ b/core/tests/mad_hatter/test_plugin.py @@ -1,19 +1,17 @@ import os -import shutil import pytest from inspect import isfunction from cat.mad_hatter.mad_hatter import Plugin from cat.mad_hatter.decorators import CatHook, CatTool - mock_plugin_path = "tests/mocks/mock_plugin/" # this fixture will give test functions a ready instantiated plugin @pytest.fixture def plugin(): - p = Plugin(mock_plugin_path, active=True) + p = Plugin(mock_plugin_path) yield p @@ -25,7 +23,7 @@ def plugin(): def test_create_plugin_wrong_folder(): with pytest.raises(Exception) as e: - Plugin("/non/existent/folder", active=True) + Plugin("/non/existent/folder") assert f"Cannot create" in str(e.value) @@ -36,14 +34,12 @@ def test_create_plugin_empty_folder(): os.mkdir(path) with pytest.raises(Exception) as e: - Plugin(path, active=True) + Plugin(path) assert f"Cannot create" in str(e.value) -def test_create_non_active_plugin(): - - plugin = Plugin(mock_plugin_path, active=False) +def test_create_plugin(plugin): assert plugin.active == False @@ -60,19 +56,12 @@ def test_create_non_active_plugin(): assert plugin.hooks == [] assert plugin.tools == [] +def test_activate_plugin(plugin): + + # activate it + plugin.activate() -def test_create_active_plugin(plugin): - assert plugin.active == True - - assert plugin.path == mock_plugin_path - assert plugin.id == "mock_plugin" - - # manifest - assert type(plugin.manifest) == dict - assert plugin.manifest["id"] == plugin.id - assert plugin.manifest["name"] == "MockPlugin" - assert "Description not found" in plugin.manifest["description"] # hooks assert len(plugin.hooks) == 1 @@ -93,24 +82,11 @@ def test_create_active_plugin(plugin): assert isfunction(tool.func) assert tool.return_direct == True +def test_deactivate_plugin(plugin): -def test_activate_plugin(): - - # create non-active plugin - plugin = Plugin(mock_plugin_path, active=False) - - # activate it + # The plugin is non active by default plugin.activate() - assert plugin.active == True - - # hooks and tools - assert len(plugin.hooks) == 1 - assert len(plugin.tools) == 1 - - -def test_deactivate_plugin(plugin): - # deactivate it plugin.deactivate()