fix(plugin): read the runtime compatibility gate from the declared snapshot (#6761)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
InfinityPacer
2026-09-23 01:44:45 +08:00
committed by GitHub
parent 0238351071
commit 3cef2149d0
14 changed files with 172 additions and 39 deletions

View File

@@ -623,7 +623,11 @@ def test_loader_runtime_gate_only_rejects_explicit_incompatible_declarations(
tmp_path,
monkeypatch,
):
"""运行目录缺少声明或 runtime 为空时保持历史插件可加载。"""
"""未建立声明或声明为空时保持历史插件可加载,只有显式 false 才拒绝。
判据来自安装时提交的声明快照。运行目录里的 ``package.json`` 是模块联邦组件的
npm manifest,主程序既不写它也不读它,这里一并钉住:它的存在不能影响门禁。
"""
from app.runtime.extensions.plugin import loader as loader_module
monkeypatch.setattr(
@@ -633,19 +637,34 @@ def test_loader_runtime_gate_only_rejects_explicit_incompatible_declarations(
)
monkeypatch.setattr(loader_module, "is_free_threaded_runtime", lambda: True)
missing = tmp_path / "missing"
missing.mkdir()
assert PluginLoader._is_runtime_compatible(missing)
declarations = {
"empty": {},
"rejected": {"v3": True, "v3t": False},
"legacygeneration": {"v3": False},
"federated": {},
}
loader = PluginLoader(
plugins_root=tmp_path,
import_preparer=lambda **_kwargs: None,
import_scanner=lambda **_kwargs: None,
runtime_declaration=lambda plugin_id: declarations.get(plugin_id, {}),
log=_logger(),
)
empty = tmp_path / "empty"
empty.mkdir()
(empty / "package.json").write_text('{"runtime": {}}', encoding="utf-8")
assert PluginLoader._is_runtime_compatible(empty)
# 未建立身份或声明快照的存量安装
assert loader.is_runtime_compatible("missing")
assert loader.is_runtime_compatible("empty")
assert not loader.is_runtime_compatible("rejected")
assert not loader.is_runtime_compatible("legacygeneration")
rejected = tmp_path / "rejected"
rejected.mkdir()
(rejected / "package.json").write_text('{"v3t": false}', encoding="utf-8")
assert not PluginLoader._is_runtime_compatible(rejected)
# 插件自带的 npm manifest 不参与判定
federated = tmp_path / "federated"
federated.mkdir()
(federated / "package.json").write_text(
'{"name": "moviepilot-federated-plugin", "v3t": false}',
encoding="utf-8",
)
assert loader.is_runtime_compatible("federated")
def test_loader_marks_incompatible_runtime_status_when_skipping(
@@ -669,7 +688,6 @@ def test_loader_marks_incompatible_runtime_status_when_skipping(
plugin_dir = tmp_path / "rejectedplugin"
plugin_dir.mkdir()
(plugin_dir / "__init__.py").write_text("", encoding="utf-8")
(plugin_dir / "package.json").write_text('{"v3t": false}', encoding="utf-8")
statuses: dict[str, PluginRuntimeStatus] = {}
loader = PluginLoader(
@@ -677,6 +695,9 @@ def test_loader_marks_incompatible_runtime_status_when_skipping(
import_preparer=lambda **_kwargs: None,
import_scanner=lambda **_kwargs: None,
runtime_status_writer=statuses.__setitem__,
runtime_declaration=lambda plugin_id: (
{"v3t": False} if plugin_id == "rejectedplugin" else {}
),
log=_logger(),
)