mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-11-15 21:01:10 +08:00
fix(module): report filter and subtitle modules as available without probing (#7357)
This commit is contained in:
@@ -184,6 +184,7 @@
|
||||
"分类策略转换失败": "Classification policy conversion failed",
|
||||
"不支持的分类策略模板": "Unsupported classification policy template",
|
||||
"模块不支持测试": "Module does not support testing",
|
||||
"模块无需探测": "Module does not require probing",
|
||||
"网络请求失败": "Network request failed",
|
||||
"TMDB请求失败": "TMDB request failed",
|
||||
"无效的媒体类型": "Invalid media type",
|
||||
|
||||
@@ -175,6 +175,7 @@
|
||||
"media_source 和 media_id 必须同时提供": "media_source 和 media_id 必须同时提供",
|
||||
"不支持的分类策略模板": "不支持的分类策略模板",
|
||||
"模块不支持测试": "模块不支持测试",
|
||||
"模块无需探测": "模块无需探测",
|
||||
"网络请求失败": "网络请求失败",
|
||||
"TMDB请求失败": "TMDB请求失败",
|
||||
"无效的媒体类型": "无效的媒体类型",
|
||||
|
||||
@@ -175,6 +175,7 @@
|
||||
"media_source 和 media_id 必须同时提供": "media_source 和 media_id 必須同時提供",
|
||||
"不支持的分类策略模板": "不支援的分類策略範本",
|
||||
"模块不支持测试": "模組不支援測試",
|
||||
"模块无需探测": "模組無需探測",
|
||||
"网络请求失败": "網路請求失敗",
|
||||
"TMDB请求失败": "TMDB 請求失敗",
|
||||
"无效的媒体类型": "無效的媒體類型",
|
||||
|
||||
@@ -129,7 +129,8 @@ class _ModuleBase(ConfigReloadMixin, metaclass=ABCMeta):
|
||||
"""
|
||||
检查模块配置或外部服务是否可用。
|
||||
|
||||
:return: 是否通过及失败说明;模块未启用或不提供检查时返回 None
|
||||
:return: 是否通过及失败说明;模块未启用时返回 None;不提供独立检查的
|
||||
已运行模块应返回成功结果并说明无需探测,而不是返回 None
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@@ -147,11 +147,13 @@ class FilterModule(_ModuleBase):
|
||||
"""
|
||||
clear_rust_parse_options_cache()
|
||||
|
||||
def test(self) -> None:
|
||||
def test(self) -> Tuple[bool, str]:
|
||||
"""
|
||||
保留模块自检入口;过滤器不依赖外部服务,无需执行探测。
|
||||
过滤器不依赖外部服务,无需执行探测;模块运行即表示可用。
|
||||
|
||||
:return: 成功结果与无需探测的说明
|
||||
"""
|
||||
return None
|
||||
return True, "模块无需探测"
|
||||
|
||||
def init_setting(self) -> Optional[Tuple[str, Union[str, bool]]]:
|
||||
"""
|
||||
|
||||
@@ -91,11 +91,13 @@ class SubtitleModule(_ModuleBase):
|
||||
"""
|
||||
pass
|
||||
|
||||
def test(self) -> Optional[Tuple[bool, str]]:
|
||||
def test(self) -> Tuple[bool, str]:
|
||||
"""
|
||||
字幕能力依赖具体资源详情页,不提供独立连接测试。
|
||||
字幕能力依赖具体资源详情页,不提供独立连接测试;模块运行即表示可用。
|
||||
|
||||
:return: 成功结果与无需探测的说明
|
||||
"""
|
||||
pass
|
||||
return True, "模块无需探测"
|
||||
|
||||
@classmethod
|
||||
def __normalize_subtitle_link(cls, page_url: str, sublink: str) -> Optional[str]:
|
||||
|
||||
104
tests/test_filter_module_health.py
Normal file
104
tests/test_filter_module_health.py
Normal file
@@ -0,0 +1,104 @@
|
||||
"""
|
||||
过滤器模块健康检查不应把“无需探测”报成“未启用”。
|
||||
|
||||
复现 #7354:运行中的 FilterModule 因 test() 返回 None,被
|
||||
ModuleManager.test() 按 falsy 结果处理成 (False, ""),健康检查接口
|
||||
据此返回 success=false,前端显示“未启用”。
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from app.api.endpoints import module as system_endpoint
|
||||
from app.modules.filter import FilterModule
|
||||
from app.runtime.extensions.module.manager import ModuleManager
|
||||
|
||||
|
||||
def test_filter_module_reports_available_without_probing() -> None:
|
||||
"""
|
||||
运行中的过滤器不依赖外部服务、无需探测,健康检查应返回成功。
|
||||
"""
|
||||
manager = ModuleManager()
|
||||
assert manager.get_running_module("FilterModule") is not None
|
||||
assert manager.test("FilterModule") == (True, "模块无需探测")
|
||||
|
||||
|
||||
def test_filter_module_test_returns_success_directly() -> None:
|
||||
"""
|
||||
过滤器自检应直接返回成功结果,而不是表示“无结论”的 None。
|
||||
"""
|
||||
assert FilterModule().test() == (True, "模块无需探测")
|
||||
|
||||
|
||||
def test_subtitle_module_reports_available_without_probing() -> None:
|
||||
"""
|
||||
字幕模块与过滤器同属“不提供独立检查”的已运行模块,应同样返回成功。
|
||||
"""
|
||||
from app.modules.subtitle import SubtitleModule
|
||||
|
||||
manager = ModuleManager()
|
||||
assert manager.get_running_module("SubtitleModule") is not None
|
||||
assert SubtitleModule().test() == (True, "模块无需探测")
|
||||
assert manager.test("SubtitleModule") == (True, "模块无需探测")
|
||||
|
||||
|
||||
def test_unselected_backend_module_keeps_old_contract() -> None:
|
||||
"""
|
||||
未选中对应后端的已运行模块(如未使用 PostgreSQL)仍保持旧合同。
|
||||
|
||||
这正是修复放在模块层而不是管理器层的原因:管理器无法区分“无需探测”
|
||||
与“后端未选用”两种 None,统一改成成功会把未选用的后端误报为可用。
|
||||
"""
|
||||
manager = ModuleManager()
|
||||
assert manager.get_running_module("PostgreSQLModule") is not None
|
||||
assert manager.test("PostgreSQLModule") == (False, "")
|
||||
|
||||
|
||||
def test_moduletest_endpoint_reports_filter_module_available() -> None:
|
||||
"""
|
||||
健康检查接口对 FilterModule 应返回 success=true。
|
||||
"""
|
||||
response = system_endpoint.moduletest("FilterModule", _="token")
|
||||
assert response.success is True
|
||||
assert response.message == "模块无需探测"
|
||||
|
||||
|
||||
def test_moduletest_endpoint_localizes_no_probing_message() -> None:
|
||||
"""
|
||||
英文请求下健康检查接口应返回翻译后的无需探测说明。
|
||||
"""
|
||||
from app.runtime.localization import LocaleHelper
|
||||
|
||||
token = LocaleHelper.set_current_locale("en-US")
|
||||
try:
|
||||
response = system_endpoint.moduletest("FilterModule", _="token")
|
||||
finally:
|
||||
LocaleHelper.reset_current_locale(token)
|
||||
assert response.success is True
|
||||
assert response.message == "Module does not require probing"
|
||||
|
||||
|
||||
def test_not_running_module_keeps_old_contract() -> None:
|
||||
"""
|
||||
未运行的模块仍保持旧合同,返回 (False, "")。
|
||||
"""
|
||||
manager = ModuleManager()
|
||||
assert manager.get_running_module("NavidromeModule") is None
|
||||
assert manager.test("NavidromeModule") == (False, "")
|
||||
|
||||
|
||||
def test_real_failure_result_still_fails(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
"""
|
||||
模块 test() 真实返回失败时,管理器应原样透传失败结果。
|
||||
"""
|
||||
manager = ModuleManager()
|
||||
monkeypatch.setattr(FilterModule, "test", lambda self: (False, "连接失败"))
|
||||
assert manager.test("FilterModule") == (False, "连接失败")
|
||||
|
||||
|
||||
def test_real_success_result_still_passes_through(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
"""
|
||||
模块 test() 真实返回成功时,管理器应原样透传成功结果。
|
||||
"""
|
||||
manager = ModuleManager()
|
||||
monkeypatch.setattr(FilterModule, "test", lambda self: (True, ""))
|
||||
assert manager.test("FilterModule") == (True, "")
|
||||
Reference in New Issue
Block a user