mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-08-21 18:39:06 +00:00
A plugin can be enabled in config, enabled in plugin state, present on disk with a valid manifest and an importable entry point -- and simply absent from the running process, with nothing anywhere to say why. That is not hypothetical. hockey-scoreboard on a live rig is enabled in both places, imports cleanly when loaded by hand, and is listed in the Vegas plugin order, but is not among the 22 plugins the process actually holds. Establishing even that much meant comparing cache-file mtimes to find it had last run three days earlier. The journal had nothing, because discovery does not report what it declines to load. Two paths were silent. A directory with no manifest.json was skipped without comment, which is defensible until it is the thing you are trying to explain. Quieter still, a manifest that parsed but carried no "id" was read successfully and then dropped on the floor -- no warning, no trace, and the plugin simply does not exist as far as the rest of the system is concerned. Both now log a warning naming the directory and the reason. This does not explain the rig above; its manifest has an id. It makes the next occurrence diagnosable from the journal instead of from file timestamps. Reverting the change fails both tests. 65 plugin-system tests pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STMbQE4YctTacQXfbYqKuW
65 lines
2.4 KiB
Python
65 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Discovery must say when it skips a directory.
|
|
|
|
A plugin can be enabled in config, enabled in plugin state, present on disk
|
|
with a valid entry point -- and simply absent from the running process, with
|
|
nothing in the journal to say why. Working that out afterwards meant comparing
|
|
cache-file mtimes to find when it had last run.
|
|
|
|
Two paths were silent. A directory with no manifest.json was ignored, and --
|
|
quieter still -- a manifest that parsed but carried no "id" was read
|
|
successfully and then dropped on the floor.
|
|
"""
|
|
import json
|
|
import logging
|
|
import sys
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
|
|
from src.plugin_system.plugin_manager import PluginManager # noqa: E402
|
|
|
|
|
|
def _manager(tmp_path):
|
|
pm = PluginManager.__new__(PluginManager)
|
|
pm.plugins_dir = tmp_path
|
|
pm.logger = logging.getLogger("test.discovery")
|
|
pm.plugin_manifests = {}
|
|
pm.plugin_directories = {}
|
|
pm._discovery_lock = __import__("threading").RLock()
|
|
pm.schema_manager = MagicMock()
|
|
return pm
|
|
|
|
|
|
def test_a_directory_without_a_manifest_is_reported(tmp_path, caplog):
|
|
(tmp_path / "not-a-plugin").mkdir()
|
|
pm = _manager(tmp_path)
|
|
with caplog.at_level(logging.WARNING, logger="test.discovery"):
|
|
pm._scan_directory_for_plugins(tmp_path)
|
|
joined = " ".join(r.message for r in caplog.records)
|
|
assert "not-a-plugin" in joined and "manifest" in joined, (
|
|
f"skip was silent; log said: {joined!r}")
|
|
|
|
|
|
def test_a_manifest_without_an_id_is_reported(tmp_path, caplog):
|
|
d = tmp_path / "idless"
|
|
d.mkdir()
|
|
(d / "manifest.json").write_text(json.dumps({"name": "No Id", "version": "1.0.0"}))
|
|
pm = _manager(tmp_path)
|
|
with caplog.at_level(logging.WARNING, logger="test.discovery"):
|
|
pm._scan_directory_for_plugins(tmp_path)
|
|
joined = " ".join(r.message for r in caplog.records)
|
|
assert "idless" in joined and "id" in joined, (
|
|
f"a parsed-but-unusable manifest vanished silently; log said: {joined!r}")
|
|
|
|
|
|
def test_a_good_plugin_still_registers(tmp_path, caplog):
|
|
d = tmp_path / "real-plugin"
|
|
d.mkdir()
|
|
(d / "manifest.json").write_text(json.dumps(
|
|
{"id": "real-plugin", "name": "Real", "version": "1.0.0"}))
|
|
pm = _manager(tmp_path)
|
|
pm._scan_directory_for_plugins(tmp_path)
|
|
assert "real-plugin" in pm.plugin_manifests, "a valid plugin was not registered"
|