From 2bffcdf81f50c703b56d9e7e9f4e1cf33550cd04 Mon Sep 17 00:00:00 2001 From: Fede Luzzi Date: Thu, 2 Jul 2026 16:44:34 -0300 Subject: [PATCH] fix some plugins --- connpy/cli/plugin_handler.py | 10 ++++++++-- connpy/completion.py | 11 +++++++---- connpy/services/plugin_service.py | 10 +++++----- connpy/tests/test_completion.py | 23 +++++++++++++++++++++++ 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/connpy/cli/plugin_handler.py b/connpy/cli/plugin_handler.py index 1325518..6501aa2 100644 --- a/connpy/cli/plugin_handler.py +++ b/connpy/cli/plugin_handler.py @@ -115,6 +115,8 @@ class PluginHandler: # Populate local plugins for name, details in local_plugins.items(): + if details.get("origin") == "core": + continue state = "Disabled" if not details.get("enabled", True) else "Active" color = "red" if state == "Disabled" else "green" @@ -123,11 +125,14 @@ class PluginHandler: state = "Shadowed (Override by Remote)" color = "yellow" - table.add_row(name, f"[{color}]{state}[/{color}]", "Local") + origin = details.get("origin", "Local").capitalize() + table.add_row(name, f"[{color}]{state}[/{color}]", origin) # Populate remote plugins if self.app.services.mode == "remote": for name, details in remote_plugins.items(): + if details.get("origin") == "core": + continue state = "Disabled" if not details.get("enabled", True) else "Active" color = "red" if state == "Disabled" else "green" @@ -138,7 +143,8 @@ class PluginHandler: state = "Shadowed (Override by Local)" color = "yellow" - table.add_row(name, f"[{color}]{state}[/{color}]", "Remote") + origin = details.get("origin", "Remote").capitalize() + table.add_row(name, f"[{color}]{state}[/{color}]", origin) if not local_plugins and not remote_plugins: printer.console.print(" No plugins found.") diff --git a/connpy/completion.py b/connpy/completion.py index e14dfe5..5c1d224 100755 --- a/connpy/completion.py +++ b/connpy/completion.py @@ -89,9 +89,9 @@ def _get_plugins(which, defaultdir): if name not in final_all_plugins or preferences.get(name) == "remote": final_all_plugins[name] = path - # Combine enabled/disabled for the helper commands - enabled_files = list(set(user_enabled + core_enabled + [k for k,v in remote_all_plugins.items() if preferences.get(k) == "remote"])) - disabled_files = list(set(user_disabled + core_disabled)) + # Combine enabled/disabled for the helper commands (excluding core plugins from management autocomplete) + enabled_files = list(set(user_enabled + [k for k,v in remote_all_plugins.items() if preferences.get(k) == "remote"])) + disabled_files = list(set(user_disabled)) # Return based on the command if which == "--disable": @@ -356,7 +356,10 @@ def _build_tree(nodes, folders, profiles, plugins, configdir): }, "plugin": { "--add": {"*": lambda w: get_cwd(w, "--add")}, - "--update": {"*": lambda w: get_cwd(w, "--update")}, + "--update": { + "__extra__": lambda w: _get_plugins("--update", configdir), + "*": lambda w: get_cwd(w, "--update") + }, "--del": lambda w: _get_plugins("--del", configdir), "--enable": lambda w: _get_plugins("--enable", configdir), "--disable": lambda w: _get_plugins("--disable", configdir), diff --git a/connpy/services/plugin_service.py b/connpy/services/plugin_service.py index 771b6c6..938adde 100644 --- a/connpy/services/plugin_service.py +++ b/connpy/services/plugin_service.py @@ -64,7 +64,7 @@ class PluginService(BaseService): if f.endswith(".py"): name = f[:-3] path = os.path.join(core_dir, f) - all_plugin_info[name] = {"enabled": True, "hash": get_hash(path)} + all_plugin_info[name] = {"enabled": True, "hash": get_hash(path), "origin": "core"} # 2. Scan shared plugins (medium priority) if hasattr(self.config, "_shared_config") and self.config._shared_config: @@ -74,10 +74,10 @@ class PluginService(BaseService): if f.endswith(".py"): name = f[:-3] path = os.path.join(shared_dir, f) - all_plugin_info[name] = {"enabled": True, "hash": get_hash(path)} + all_plugin_info[name] = {"enabled": True, "hash": get_hash(path), "origin": "shared"} elif f.endswith(".py.bkp"): name = f[:-7] - all_plugin_info[name] = {"enabled": False} + all_plugin_info[name] = {"enabled": False, "origin": "shared"} # 3. Scan user plugins (highest priority) user_dir = os.path.join(self.config.defaultdir, "plugins") @@ -86,10 +86,10 @@ class PluginService(BaseService): if f.endswith(".py"): name = f[:-3] path = os.path.join(user_dir, f) - all_plugin_info[name] = {"enabled": True, "hash": get_hash(path)} + all_plugin_info[name] = {"enabled": True, "hash": get_hash(path), "origin": "user"} elif f.endswith(".py.bkp"): name = f[:-7] - all_plugin_info[name] = {"enabled": False} + all_plugin_info[name] = {"enabled": False, "origin": "user"} return all_plugin_info diff --git a/connpy/tests/test_completion.py b/connpy/tests/test_completion.py index af6c88f..8b2a6b8 100644 --- a/connpy/tests/test_completion.py +++ b/connpy/tests/test_completion.py @@ -241,5 +241,28 @@ class TestSsoCompletions: assert "authelia" in completions +class TestPluginUpdateCompletion: + def test_plugin_update_first_arg_suggests_plugins(self, tmp_path): + from connpy.completion import _build_tree, resolve_completion + + # Create a mock user plugin + plugins_dir = tmp_path / "plugins" + plugins_dir.mkdir(parents=True, exist_ok=True) + (plugins_dir / "my_custom_plugin.py").touch() + + # Build tree with plugin mock dict + plugins = {"my_custom_plugin": str(plugins_dir / "my_custom_plugin.py")} + tree = _build_tree([], [], [], plugins, str(tmp_path)) + + # First argument of --update should suggest my_custom_plugin + completions = resolve_completion(["plugin", "--update", ""], tree) + assert "my_custom_plugin" in completions + + # Second argument should suggest file paths (calling get_cwd) + # Type "plugin --update my_custom_plugin " + file_completions = resolve_completion(["plugin", "--update", "my_custom_plugin", ""], tree) + assert isinstance(file_completions, list) + +