mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-11-03 13:55:00 +08:00
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:
@@ -16,6 +16,7 @@ from app.application.plugin.identity import (
|
||||
normalize_physical_plugin_id,
|
||||
)
|
||||
from app.application.plugin.inventory import normalize_github_plugin_source
|
||||
from app.domain.plugin import check_plugin_runtime_compatibility
|
||||
from app.schemas.plugin import (
|
||||
Plugin,
|
||||
PluginSourceBindingStatus,
|
||||
@@ -44,12 +45,26 @@ class _CatalogLoadRequest:
|
||||
def apply_declared_metadata_fallback(
|
||||
plugins: Sequence[Plugin],
|
||||
identities: Mapping[str, PluginIdentity],
|
||||
*,
|
||||
free_threaded: bool = False,
|
||||
) -> list[Plugin]:
|
||||
"""用已提交快照补齐加载失败插件,不覆盖真实运行态字段。"""
|
||||
"""用已提交快照补齐加载失败插件,不覆盖真实运行态字段。
|
||||
|
||||
:param free_threaded: 当前是否运行在 free-threaded 解释器;已安装卡片的运行时
|
||||
不兼容提示只能来自安装时提交的声明快照,市场候选那条标注路径要联网才有。
|
||||
"""
|
||||
result: list[Plugin] = []
|
||||
for plugin in plugins:
|
||||
identity = identities.get((plugin.id or "").lower())
|
||||
updates: dict[str, object] = {}
|
||||
if identity is not None and identity.declared_metadata is not None:
|
||||
compatible, message = check_plugin_runtime_compatibility(
|
||||
identity.declared_metadata.to_json().get("runtime"),
|
||||
free_threaded=free_threaded,
|
||||
)
|
||||
if not compatible:
|
||||
updates["runtime_compatible"] = False
|
||||
updates["runtime_message"] = message
|
||||
if plugin.installed and not plugin.is_instance:
|
||||
if identity is None:
|
||||
updates["source_binding_status"] = PluginSourceBindingStatus.BINDING_REQUIRED
|
||||
@@ -469,14 +484,16 @@ class PluginCatalogQuery:
|
||||
online_candidates: Callable[[bool], Awaitable[list[Plugin]]],
|
||||
process_plugins: Callable[[list[Plugin], list[Plugin]], list[Plugin]],
|
||||
identities: Callable[[list[str]], Awaitable[list[PluginIdentity]]],
|
||||
free_threaded: Callable[[], bool],
|
||||
) -> None:
|
||||
"""保存运行态目录和来源身份读取窄端口。"""
|
||||
"""保存运行态目录、来源身份读取和解释器变体判定窄端口。"""
|
||||
self._installed_plugins = installed_plugins
|
||||
self._local_plugins = local_plugins
|
||||
self._local_repo_plugins = local_repo_plugins
|
||||
self._online_candidates = online_candidates
|
||||
self._process_plugins = process_plugins
|
||||
self._identities = identities
|
||||
self._free_threaded = free_threaded
|
||||
|
||||
async def query(
|
||||
self, *, state: str = "all", force: bool = False
|
||||
@@ -554,6 +571,7 @@ class PluginCatalogQuery:
|
||||
return apply_declared_metadata_fallback(
|
||||
plugins,
|
||||
{identity.normalized_plugin_id: identity for identity in identities},
|
||||
free_threaded=self._free_threaded(),
|
||||
)
|
||||
|
||||
def _prefer_bound_update(
|
||||
|
||||
@@ -46,6 +46,7 @@ class PluginReleaseService:
|
||||
has_release_cache: ReleaseCacheProbe,
|
||||
releases: ReleaseLoader,
|
||||
refresh_releases: ReleaseRefresher,
|
||||
free_threaded: Callable[[], bool],
|
||||
) -> None:
|
||||
"""保存源身份归一、运行态、来源身份和市场读取窄端口。"""
|
||||
self._source_plugin_id = source_plugin_id
|
||||
@@ -59,6 +60,7 @@ class PluginReleaseService:
|
||||
self._has_release_cache = has_release_cache
|
||||
self._releases = releases
|
||||
self._refresh_releases = refresh_releases
|
||||
self._free_threaded = free_threaded
|
||||
|
||||
async def history(self, plugin_id: str, *, force: bool = True) -> Plugin | None:
|
||||
"""按可信绑定仓库读取单个已安装插件的更新说明。
|
||||
@@ -80,6 +82,7 @@ class PluginReleaseService:
|
||||
installed_plugin = apply_declared_metadata_fallback(
|
||||
[installed_plugin],
|
||||
{identity.normalized_plugin_id: identity},
|
||||
free_threaded=self._free_threaded(),
|
||||
)[0]
|
||||
|
||||
local_plugin = next(
|
||||
|
||||
Reference in New Issue
Block a user