From d25f45d09c7ad4189ce7f8f21ce5b8b466c7d2c3 Mon Sep 17 00:00:00 2001 From: Gunnar Von Bergen <36426938+GVonB@users.noreply.github.com> Date: Tue, 23 Jun 2026 14:58:02 -0400 Subject: [PATCH] fix: stop silently dropping plugin entry points - Python 3.9 is EOL, with a bump to >=3.10 the group= calls are now valid - Remove the silent `except Exception: pass` guards that kept this issue hidden - Keep per-plugin load guards - Drop the obsolete test since if stdlib entry_points() fails, it's not worth trying to handle --- pyproject.toml | 2 +- team/cli.py | 17 +++++++---------- team/persona_library.py | 25 +++++++++++-------------- team/skills.py | 9 +++------ tests/test_plugin_system.py | 6 ------ 5 files changed, 22 insertions(+), 37 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 05d98f4..0321478 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ version = "0.17.0" description = "Orchestrate a cluster of containerized local LLMs (via Ollama), each with a specific persona and role, that collaborate to solve a goal." readme = "README.md" license = { file = "LICENSE" } -requires-python = ">=3.9" +requires-python = ">=3.10" authors = [{ name = "Fabio Cumbo" }] keywords = ["llm", "ollama", "multi-agent", "orchestration", "docker", "agents"] classifiers = [ diff --git a/team/cli.py b/team/cli.py index c216dc1..7e482e2 100644 --- a/team/cli.py +++ b/team/cli.py @@ -170,16 +170,13 @@ def _load_plugin_commands() -> None: Errors loading individual plugins are logged and skipped so one bad plugin does not prevent ``team`` from starting. """ - try: - for ep in entry_points(group="team.commands"): - try: - cmd = ep.load() - cli.add_command(cmd, name=ep.name) - log.debug("cli: loaded plugin command %r from %s", ep.name, ep.value) - except Exception as exc: # noqa: BLE001 - log.warning("cli: failed to load plugin command %r: %s", ep.name, exc) - except Exception: # noqa: BLE001 - pass # importlib.metadata not available in very old environments + for ep in entry_points(group="team.commands"): + try: + cmd = ep.load() + cli.add_command(cmd, name=ep.name) + log.debug("cli: loaded plugin command %r from %s", ep.name, ep.value) + except Exception as exc: # noqa: BLE001 + log.warning("cli: failed to load plugin command %r: %s", ep.name, exc) _load_plugin_commands() diff --git a/team/persona_library.py b/team/persona_library.py index 62c8559..5b6a6d4 100644 --- a/team/persona_library.py +++ b/team/persona_library.py @@ -88,20 +88,17 @@ def _persona_dirs() -> list[tuple[Path, str]]: dirs.append((custom, "env (TEAM_PERSONA_DIR)")) # 2. Entry-point registered persona directories. - try: - known_paths = {p for p, _ in dirs} - for ep in entry_points(group="team.persona_dirs"): - try: - fn = ep.load() - p = Path(fn()).expanduser().resolve() - if p.is_dir() and p not in known_paths: - dirs.append((p, ep.name)) - known_paths.add(p) - log.debug("persona_library: loaded persona dir from plugin %r: %s", ep.name, p) - except Exception as exc: # noqa: BLE001 - log.warning("persona_library: failed to load persona dir from plugin %r: %s", ep.name, exc) - except Exception: # noqa: BLE001 - pass # importlib.metadata not available in very old environments + known_paths = {p for p, _ in dirs} + for ep in entry_points(group="team.persona_dirs"): + try: + fn = ep.load() + p = Path(fn()).expanduser().resolve() + if p.is_dir() and p not in known_paths: + dirs.append((p, ep.name)) + known_paths.add(p) + log.debug("persona_library: loaded persona dir from plugin %r: %s", ep.name, p) + except Exception as exc: # noqa: BLE001 + log.warning("persona_library: failed to load persona dir from plugin %r: %s", ep.name, exc) # 3. Built-in directory — lowest priority. if _BUILTIN_DIR.is_dir(): diff --git a/team/skills.py b/team/skills.py index 0c8b42f..0f656e8 100644 --- a/team/skills.py +++ b/team/skills.py @@ -194,12 +194,9 @@ def _load_skill_registry() -> dict[str, str]: return _SKILL_REGISTRY registry: dict[str, str] = {} - try: - for ep in entry_points(group="team.skills"): - registry[ep.name] = ep.value - log.debug("skill registry: registered %r → %s", ep.name, ep.value) - except Exception: # noqa: BLE001 - pass # importlib.metadata not available in very old environments + for ep in entry_points(group="team.skills"): + registry[ep.name] = ep.value + log.debug("skill registry: registered %r → %s", ep.name, ep.value) _SKILL_REGISTRY = registry return _SKILL_REGISTRY diff --git a/tests/test_plugin_system.py b/tests/test_plugin_system.py index a741c5d..e75ad86 100644 --- a/tests/test_plugin_system.py +++ b/tests/test_plugin_system.py @@ -75,12 +75,6 @@ def test_result_is_cached(self): skills_mod._load_skill_registry() assert m.call_count == 1 # entry_points only called once - def test_importlib_error_yields_empty(self): - # If importlib.metadata raises, we get an empty dict (graceful degradation). - with patch("team.skills.entry_points", side_effect=RuntimeError("no metadata")): - registry = skills_mod._load_skill_registry() - assert registry == {} - # --------------------------------------------------------------------------- # # _load_skill_by_name