Files
hermes-agent/tests/plugins/test_plugin_loader_unreadable.py
teknium1 e3a90079b4 fix(plugins): one unreadable plugin child no longer aborts iter_plugin_dirs or memory-provider discovery
iter_plugin_dirs stat'd <child>/__init__.py inside every plugin dir, so a
single mode-000 / ACL-denied $HERMES_HOME/plugins/<x> still raised
PermissionError out of the loader, memory-provider discovery (dashboard
memory settings, hermes memory setup, plugins memory picker) and the
user cron-provider scan. Catch OSError per child and log the same
'Skipping unreadable plugin directory' warning the list path already emits.

Part of #111804
2026-09-15 18:48:59 -07:00

31 lines
1.1 KiB
Python

"""One mode-000 / ACL-denied child under a plugin root must not abort the listing (#111804)."""
from __future__ import annotations
from pathlib import Path
from plugins import plugin_loader
def _deny(monkeypatch, denied: Path) -> None:
"""chmod 000 does not bite as root, so fail the stat of the denied child's ``__init__.py``."""
real_stat = Path.stat
def stat(self, *args, **kwargs):
if self.parent == denied:
raise PermissionError(13, "Permission denied", str(self))
return real_stat(self, *args, **kwargs)
monkeypatch.setattr(Path, "stat", stat)
def test_iter_plugin_dirs_skips_unreadable_child(tmp_path, monkeypatch, caplog):
for name in ("denied", "good"):
(tmp_path / name).mkdir()
(tmp_path / name / "__init__.py").write_text("", encoding="utf-8")
_deny(monkeypatch, tmp_path / "denied")
with caplog.at_level("WARNING", logger="plugins.plugin_loader"):
assert plugin_loader.iter_plugin_dirs(tmp_path) == [tmp_path / "good"]
assert "Skipping unreadable plugin directory" in caplog.text