refactor: unify subscribe chain data ports

This commit is contained in:
jxxghp
2026-08-24 04:43:20 +08:00
parent f93ecf65d3
commit 4346fc0559
10 changed files with 125 additions and 86 deletions
+21
View File
@@ -522,6 +522,27 @@ def test_download_chain_uses_explicit_data_port_getters():
assert violations == []
def test_subscribe_chain_uses_explicit_data_port_getters():
"""订阅链不得把三个迁移期 PortProxy 伪装成数据库 Oper。"""
path = APP_ROOT / "chain" / "subscribe.py"
tree = ast.parse(path.read_text(encoding="utf-8-sig"), filename=str(path))
forbidden = {
"DownloadHistoryPortProxy",
"SitePortProxy",
"SubscribePortProxy",
}
violations = [
f"{path.relative_to(PROJECT_ROOT).as_posix()}:{node.lineno}:{alias.name}"
for node in ast.walk(tree)
if isinstance(node, ast.ImportFrom)
and node.module == "app.application.chain.data"
for alias in node.names
if alias.name in forbidden
]
assert violations == []
def test_plugin_components_do_not_reexport_legacy_abi_names():
"""新插件组件只提供 canonical 能力,不得复制旧 Helper、Manager 或 Oper 导出。"""
violations: list[str] = []
+9 -9
View File
@@ -343,7 +343,7 @@ def test_album_best_version_requires_confirmed_full_coverage():
chain = SubscribeChain()
with patch("app.chain.subscribe.DownloadChain", return_value=download_chain), \
patch("app.chain.subscribe.SubscribeOper", return_value=subscribe_oper), \
patch("app.chain.subscribe.get_chain_subscribe_port", return_value=subscribe_oper), \
patch.object(chain, "_SubscribeChain__finish_subscribe") as finish:
chain._download_music_subscribe(subscribe, album, [downloaded])
@@ -440,7 +440,7 @@ def test_music_rss_match_reuses_cached_context_without_second_site_search():
torrent_helper = Mock()
torrent_helper.filter_torrent.return_value = True
with patch.object(SubscribeChain, "_recognize_music_subscribe", return_value=target), \
patch("app.chain.subscribe.SubscribeOper", return_value=subscribe_oper), \
patch("app.chain.subscribe.get_chain_subscribe_port", return_value=subscribe_oper), \
patch("app.chain._music.get_chain_subscribe_port", return_value=subscribe_oper), \
patch("app.chain._music.TorrentHelper", return_value=torrent_helper), \
patch("app.chain._music.DownloadChain", return_value=download_chain), \
@@ -662,7 +662,7 @@ def test_album_target_sync_does_not_clear_stable_track_count():
)
subscribe_oper = Mock()
with patch("app.chain.subscribe.SubscribeOper", return_value=subscribe_oper):
with patch("app.chain.subscribe.get_chain_subscribe_port", return_value=subscribe_oper):
SubscribeChain._sync_music_subscribe_target(subscribe, album)
subscribe_oper.update.assert_not_called()
@@ -707,7 +707,7 @@ def test_subscribe_add_music_uses_explicit_entity_recognize():
add_subscribe = Mock(return_value=(1, ""))
with patch("app.chain.subscribe.MediaChain", return_value=media_chain), \
patch("app.chain.subscribe.SubscribeOper", return_value=subscribe_oper), \
patch("app.chain.subscribe.get_chain_subscribe_port", return_value=subscribe_oper), \
patch("app.chain.subscribe.add_subscribe", add_subscribe), \
patch("app.chain.subscribe.MoviePilotServerHelper"), \
patch("app.chain.subscribe.eventmanager"):
@@ -759,7 +759,7 @@ def test_subscribe_add_music_routes_new_album_sources(
add_subscribe = Mock(return_value=(1, ""))
with patch("app.chain.subscribe.MediaChain", return_value=media_chain), \
patch("app.chain.subscribe.SubscribeOper", return_value=subscribe_oper), \
patch("app.chain.subscribe.get_chain_subscribe_port", return_value=subscribe_oper), \
patch("app.chain.subscribe.add_subscribe", add_subscribe), \
patch("app.chain.subscribe.MoviePilotServerHelper"), \
patch("app.chain.subscribe.eventmanager"):
@@ -792,7 +792,7 @@ def test_subscribe_add_rejects_music_entity_mismatch_before_database_write():
add_subscribe = Mock()
with patch("app.chain.subscribe.MediaChain", return_value=media_chain), \
patch("app.chain.subscribe.SubscribeOper", return_value=subscribe_oper), \
patch("app.chain.subscribe.get_chain_subscribe_port", return_value=subscribe_oper), \
patch("app.chain.subscribe.add_subscribe", add_subscribe):
sid, err_msg = SubscribeChain().add(
title="叶惠美",
@@ -819,7 +819,7 @@ def test_subscribe_add_music_fails_fast_on_offline_fallback():
add_subscribe = Mock(return_value=(1, ""))
with patch("app.chain.subscribe.MediaChain", return_value=media_chain), \
patch("app.chain.subscribe.SubscribeOper", return_value=subscribe_oper), \
patch("app.chain.subscribe.get_chain_subscribe_port", return_value=subscribe_oper), \
patch("app.chain.subscribe.add_subscribe", add_subscribe):
sid, err_msg = SubscribeChain().add(
title="未知曲目",
@@ -852,7 +852,7 @@ def test_follow_preserves_album_entity_and_track_count():
system_config = Mock()
system_config.get.return_value = ["follow-user"]
with patch("app.chain.subscribe.SubscribeOper", return_value=subscribe_oper), \
with patch("app.chain.subscribe.get_chain_subscribe_port", return_value=subscribe_oper), \
patch("app.chain.subscribe.get_configured_system_config", return_value=system_config), \
patch(
"app.chain.subscribe.MoviePilotServerHelper.get_subscribe_shares",
@@ -878,7 +878,7 @@ def test_refresh_enables_music_entry_fetch_when_music_subscribe_exists():
torrents_chain = Mock()
torrents_chain.refresh.return_value = {}
with patch("app.chain.subscribe.SubscribeOper", return_value=subscribe_oper), \
with patch("app.chain.subscribe.get_chain_subscribe_port", return_value=subscribe_oper), \
patch("app.chain.subscribe.get_configured_system_config") as system_config, \
patch("app.chain.subscribe.TorrentsChain", return_value=torrents_chain):
system_config.return_value.get.return_value = []
+3 -1
View File
@@ -236,8 +236,10 @@ class TestSlashCommandInteractions(unittest.TestCase):
)
]
subscribe_port = SimpleNamespace(list=lambda: fake_subscribes)
with patch(
"app.chain.subscribe.SubscribeOper.list", return_value=fake_subscribes
"app.chain.subscribe.get_chain_subscribe_port",
return_value=subscribe_port,
), patch.object(chain, "post_message") as post_message:
chain.remote_list(channel=NotificationChannel.Web, userid="u1", source="web")
+56 -48
View File
@@ -257,6 +257,13 @@ def _load_subscribe_chain_class():
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
class _SubscribeDeletedEventData:
"""提供订阅删除应用服务在隔离加载时需要的事件快照。"""
def __init__(self, **kwargs):
"""保存事件字段,行为与测试所需的 schema 投影一致。"""
self.__dict__.update(kwargs)
mediaserver_schema_module = ensure_module(
"app.schemas.mediaserver",
types.ModuleType("app.schemas.mediaserver"),
@@ -293,6 +300,7 @@ def _load_subscribe_chain_class():
event_schema_module.SubscribeCompletionCheckEventData = (
_SubscribeCompletionCheckEventData
)
event_schema_module.SubscribeDeletedEventData = _SubscribeDeletedEventData
logger_module = ensure_module("app.runtime.log", types.ModuleType("app.runtime.log"))
@@ -586,7 +594,7 @@ class SubscribeChainTest(TestCase):
chain = SubscribeChain()
chain.check_and_handle_existing_media = lambda **kwargs: (False, {})
with patch.object(SUBSCRIBE_CHAIN_MODULE, "SubscribeOper", _SubscribeOper), patch.object(
with patch.object(SUBSCRIBE_CHAIN_MODULE, "get_chain_subscribe_port", _SubscribeOper), patch.object(
SUBSCRIBE_CHAIN_MODULE,
"TorrentHelper",
_PlainTorrentHelper,
@@ -669,7 +677,7 @@ class SubscribeChainTest(TestCase):
chain.filter_torrents = lambda **_kwargs: [context.torrent_info]
chain.finish_subscribe_or_not = lambda **_kwargs: None
with patch.object(SUBSCRIBE_CHAIN_MODULE, "SubscribeOper", _SubscribeOper), patch.object(
with patch.object(SUBSCRIBE_CHAIN_MODULE, "get_chain_subscribe_port", _SubscribeOper), patch.object(
SUBSCRIBE_CHAIN_MODULE,
"TorrentHelper",
_TorrentHelper,
@@ -834,7 +842,7 @@ class SubscribeChainTest(TestCase):
with patch.object(SUBSCRIBE_CHAIN_MODULE, "DownloadChain", _DownloadChain), patch.object(
SUBSCRIBE_CHAIN_MODULE,
"SubscribeOper",
"get_chain_subscribe_port",
_SubscribeOper,
):
satisfied, no_exists = chain.resolve_subscribe_missing(
@@ -1054,7 +1062,7 @@ class SubscribeChainTest(TestCase):
def _metainfo(title):
return SimpleNamespace(name=title, begin_season=None, episode_list=[])
with patch.object(SUBSCRIBE_CHAIN_MODULE, "SubscribeOper", _SubscribeOper), patch.object(
with patch.object(SUBSCRIBE_CHAIN_MODULE, "get_chain_subscribe_port", _SubscribeOper), patch.object(
SUBSCRIBE_CHAIN_MODULE,
"get_configured_system_config",
_SystemConfigOper,
@@ -1699,7 +1707,7 @@ class SubscribeChainTest(TestCase):
chain = SubscribeChain()
mediainfo = SimpleNamespace(title_year="Test Show (2026)")
with patch.object(SUBSCRIBE_CHAIN_MODULE, "SubscribeOper") as subscribe_oper_cls:
with patch.object(SUBSCRIBE_CHAIN_MODULE, "get_chain_subscribe_port") as subscribe_oper_cls:
subscribe_oper = subscribe_oper_cls.return_value
subscribe_oper.update.return_value = None
@@ -1734,7 +1742,7 @@ class SubscribeChainTest(TestCase):
chain = SubscribeChain()
mediainfo = SimpleNamespace(title_year="Test Show (2026)")
with patch.object(SUBSCRIBE_CHAIN_MODULE, "SubscribeOper") as subscribe_oper_cls, \
with patch.object(SUBSCRIBE_CHAIN_MODULE, "get_chain_subscribe_port") as subscribe_oper_cls, \
patch.object(SUBSCRIBE_CHAIN_MODULE, "logger") as logger_mock:
subscribe_oper = subscribe_oper_cls.return_value
subscribe_oper.update.return_value = None
@@ -1767,7 +1775,7 @@ class SubscribeChainTest(TestCase):
chain = SubscribeChain()
mediainfo = SimpleNamespace(title_year="Test Show (2026)")
with patch.object(SUBSCRIBE_CHAIN_MODULE, "SubscribeOper") as subscribe_oper_cls:
with patch.object(SUBSCRIBE_CHAIN_MODULE, "get_chain_subscribe_port") as subscribe_oper_cls:
subscribe_oper = subscribe_oper_cls.return_value
subscribe_oper.update.return_value = None
@@ -1794,7 +1802,7 @@ class SubscribeChainTest(TestCase):
chain = SubscribeChain()
mediainfo = SimpleNamespace(title_year="Test Show (2026)")
with patch.object(SUBSCRIBE_CHAIN_MODULE, "SubscribeOper") as subscribe_oper_cls:
with patch.object(SUBSCRIBE_CHAIN_MODULE, "get_chain_subscribe_port") as subscribe_oper_cls:
subscribe_oper = subscribe_oper_cls.return_value
subscribe_oper.update.return_value = None
@@ -1826,7 +1834,7 @@ class SubscribeChainTest(TestCase):
meta = SimpleNamespace(type=MediaType.TV)
mediainfo = SimpleNamespace(title_year="Test Show (2026)")
with patch.object(SUBSCRIBE_CHAIN_MODULE, "SubscribeOper") as subscribe_oper_cls, patch.object(
with patch.object(SUBSCRIBE_CHAIN_MODULE, "get_chain_subscribe_port") as subscribe_oper_cls, patch.object(
SubscribeChain,
"_SubscribeChain__finish_subscribe",
) as finish_mock:
@@ -1868,7 +1876,7 @@ class SubscribeChainTest(TestCase):
get_backdrop_image=lambda: "backdrop",
)
with patch.object(SUBSCRIBE_CHAIN_MODULE, "SubscribeOper") as subscribe_oper_cls, \
with patch.object(SUBSCRIBE_CHAIN_MODULE, "get_chain_subscribe_port") as subscribe_oper_cls, \
_patch_media_recognize(SUBSCRIBE_CHAIN_MODULE, mediainfo):
subscribe_oper = subscribe_oper_cls.return_value
subscribe_oper.list.return_value = [subscribe]
@@ -2084,7 +2092,7 @@ class SubscribeNoteTrackingTest(TestCase):
def get(self, *args, **kwargs):
return subscribe
with patch.object(SUBSCRIBE_CHAIN_MODULE, "SubscribeOper", _SubscribeOper), patch.object(
with patch.object(SUBSCRIBE_CHAIN_MODULE, "get_chain_subscribe_port", _SubscribeOper), patch.object(
SubscribeChain,
"_SubscribeChain__update_movie_download_priority",
), patch.object(
@@ -2124,7 +2132,7 @@ class SubscribeNoteTrackingTest(TestCase):
def get(self, *args, **kwargs):
return subscribe
with patch.object(SUBSCRIBE_CHAIN_MODULE, "SubscribeOper", _SubscribeOper), patch.object(
with patch.object(SUBSCRIBE_CHAIN_MODULE, "get_chain_subscribe_port", _SubscribeOper), patch.object(
SubscribeChain,
"_SubscribeChain__is_best_version_complete",
return_value=False,
@@ -2266,7 +2274,7 @@ class SubscribeProgressEntrypointTest(TestCase):
def update(self, subscribe_id, payload):
updates.append((subscribe_id, payload))
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()):
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()):
summary = self.SubscribeChain().backfill_existing_episodes(
subscribe,
[1, 2, 3, 9, "bad"],
@@ -2293,7 +2301,7 @@ class SubscribeProgressEntrypointTest(TestCase):
def update(self, subscribe_id, payload):
updates.append(payload)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()):
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()):
summary = self.SubscribeChain().backfill_existing_episodes(
subscribe,
[1, 2, 3],
@@ -2315,7 +2323,7 @@ class SubscribeProgressEntrypointTest(TestCase):
def update(self, subscribe_id, payload):
updates.append(payload)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()):
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()):
invalid = self.SubscribeChain().backfill_existing_episodes(
subscribe,
[1, 2],
@@ -2359,7 +2367,7 @@ class SubscribeProgressEntrypointTest(TestCase):
def update(self, subscribe_id, payload):
updates.append(payload)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()):
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()):
summary = self.SubscribeChain().backfill_existing_episodes(
subscribe,
[1],
@@ -2381,7 +2389,7 @@ class SubscribeProgressEntrypointTest(TestCase):
def update(self, subscribe_id, payload):
updates.append(payload)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()):
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()):
summary = self.SubscribeChain().backfill_existing_episodes(
subscribe,
[1],
@@ -2404,7 +2412,7 @@ class SubscribeProgressEntrypointTest(TestCase):
def update(self, subscribe_id, payload):
updates.append(payload)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()):
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()):
summary = self.SubscribeChain().backfill_existing_episodes(
subscribe,
[1, 2, 3, 4, 5],
@@ -2430,7 +2438,7 @@ class SubscribeProgressEntrypointTest(TestCase):
def update(self, subscribe_id, payload):
updates.append(payload)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()):
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()):
self.SubscribeChain().backfill_existing_episodes(
subscribe,
[3],
@@ -2453,7 +2461,7 @@ class SubscribeProgressEntrypointTest(TestCase):
updates.append(payload)
chain = self.SubscribeChain()
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()), \
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()), \
patch.object(chain, "refresh_subscribe_progress", return_value={
"scene": "unit",
"updated": True,
@@ -2489,7 +2497,7 @@ class SubscribeProgressEntrypointTest(TestCase):
def update(self, subscribe_id, payload):
updates.append(payload)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()):
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()):
summary = self.SubscribeChain()._SubscribeChain__refresh_subscribe_progress_with_no_exists(
subscribe=subscribe,
no_exists={},
@@ -2515,7 +2523,7 @@ class SubscribeProgressEntrypointTest(TestCase):
def update(self, subscribe_id, payload):
updates.append(payload)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()):
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()):
self.SubscribeChain()._SubscribeChain__refresh_subscribe_progress_with_no_exists(
subscribe=subscribe,
no_exists={},
@@ -2547,7 +2555,7 @@ class SubscribeProgressEntrypointTest(TestCase):
def update(self, subscribe_id, payload):
updates.append(payload)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()), \
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()), \
_patch_media_recognize(self.module, mediainfo), \
patch.object(self.SubscribeChain, "resolve_subscribe_missing", return_value=(False, no_exists)) as resolve_missing:
summary = self.SubscribeChain().refresh_subscribe_progress(subscribe, scene="unit")
@@ -2580,7 +2588,7 @@ class SubscribeProgressEntrypointTest(TestCase):
def update(self, subscribe_id, payload):
raise AssertionError("resolve failure must not write progress")
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()), \
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()), \
_patch_media_recognize(self.module, mediainfo), \
patch.object(self.SubscribeChain, "resolve_subscribe_missing", return_value=(False, {})):
summary = self.SubscribeChain().refresh_subscribe_progress(subscribe, scene="unit")
@@ -2596,7 +2604,7 @@ class SubscribeProgressEntrypointTest(TestCase):
def update(self, subscribe_id, payload):
raise AssertionError("recognition failure must not write progress")
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()), \
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()), \
_patch_media_recognize(self.module, None):
summary = self.SubscribeChain().refresh_subscribe_progress(subscribe, scene="unit")
@@ -2618,7 +2626,7 @@ class SubscribeProgressEntrypointTest(TestCase):
def update(self, subscribe_id, payload):
updates.append(payload)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()), \
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()), \
patch.object(self.SubscribeChain, "_SubscribeChain__finish_subscribe"):
self.SubscribeChain().finish_subscribe_or_not(
subscribe=subscribe,
@@ -2738,7 +2746,7 @@ class SubscribeProgressConsolidationTest(TestCase):
def update(self, subscribe_id, payload):
updates.append((subscribe_id, payload))
with patch.object(module, "SubscribeOper", return_value=_SubscribeOper()):
with patch.object(module, "get_chain_subscribe_port", return_value=_SubscribeOper()):
SubscribeChain()._SubscribeChain__refresh_total_episode_before_completion(
subscribe,
mediainfo,
@@ -2789,7 +2797,7 @@ class SubscribeProgressConsolidationTest(TestCase):
chain.resolve_subscribe_missing = _resolve_missing
with patch.object(module, "SubscribeOper", return_value=_SubscribeOper()), patch.object(
with patch.object(module, "get_chain_subscribe_port", return_value=_SubscribeOper()), patch.object(
module,
"eventmanager",
eventmanager,
@@ -2832,7 +2840,7 @@ class SubscribeProgressConsolidationTest(TestCase):
def update(self, subscribe_id, payload):
updates.append((subscribe_id, payload))
with patch.object(module, "SubscribeOper", return_value=_SubscribeOper()), patch.object(
with patch.object(module, "get_chain_subscribe_port", return_value=_SubscribeOper()), patch.object(
module,
"eventmanager",
eventmanager,
@@ -2968,7 +2976,7 @@ class SubscribeProgressConsolidationTest(TestCase):
def update(self, subscribe_id, payload):
updates.append((subscribe_id, payload))
with patch.object(module, "SubscribeOper", return_value=_SubscribeOper()), patch.object(
with patch.object(module, "get_chain_subscribe_port", return_value=_SubscribeOper()), patch.object(
module,
"eventmanager",
eventmanager,
@@ -3017,7 +3025,7 @@ class SubscribeProgressConsolidationTest(TestCase):
def update(self, subscribe_id, payload):
updates.append((subscribe_id, payload))
with patch.object(module, "SubscribeOper", return_value=_SubscribeOper()), patch.object(
with patch.object(module, "get_chain_subscribe_port", return_value=_SubscribeOper()), patch.object(
module,
"eventmanager",
eventmanager,
@@ -3066,7 +3074,7 @@ class SubscribeProgressConsolidationTest(TestCase):
def update(self, subscribe_id, payload):
updates.append((subscribe_id, payload))
with patch.object(module, "SubscribeOper", return_value=_SubscribeOper()), patch.object(
with patch.object(module, "get_chain_subscribe_port", return_value=_SubscribeOper()), patch.object(
module,
"eventmanager",
eventmanager,
@@ -3109,7 +3117,7 @@ class SubscribeProgressConsolidationTest(TestCase):
def update(self, *_args, **_kwargs):
raise AssertionError("manual total episode must not be updated")
with patch.object(module, "SubscribeOper", return_value=_SubscribeOper()), patch.object(
with patch.object(module, "get_chain_subscribe_port", return_value=_SubscribeOper()), patch.object(
module,
"eventmanager",
_EventManager(),
@@ -3150,7 +3158,7 @@ class SubscribeProgressConsolidationTest(TestCase):
def update(self, *_args, **_kwargs):
raise AssertionError("non-tv subscribe must not be updated")
with patch.object(module, "SubscribeOper", return_value=_SubscribeOper()), patch.object(
with patch.object(module, "get_chain_subscribe_port", return_value=_SubscribeOper()), patch.object(
module,
"eventmanager",
_EventManager(),
@@ -3195,7 +3203,7 @@ class SubscribeProgressConsolidationTest(TestCase):
chain = SubscribeChain()
with patch.object(module, "SubscribeOper", return_value=_SubscribeOper()), \
with patch.object(module, "get_chain_subscribe_port", return_value=_SubscribeOper()), \
_patch_media_recognize(module, lambda **_kwargs: self._mediainfo(total_episode=5)):
chain.check()
@@ -3241,7 +3249,7 @@ class SubscribeProgressConsolidationTest(TestCase):
chain = SubscribeChain()
with patch.object(module, "SubscribeOper", return_value=_SubscribeOper()), patch.object(
with patch.object(module, "get_chain_subscribe_port", return_value=_SubscribeOper()), patch.object(
module,
"eventmanager",
eventmanager,
@@ -3300,7 +3308,7 @@ class SubscribeProgressConsolidationTest(TestCase):
},
)
with patch.object(module, "SubscribeOper", return_value=_SubscribeOper()), patch.object(
with patch.object(module, "get_chain_subscribe_port", return_value=_SubscribeOper()), patch.object(
module,
"eventmanager",
eventmanager,
@@ -3350,7 +3358,7 @@ class SubscribeProgressConsolidationTest(TestCase):
chain = SubscribeChain()
with patch.object(module, "SubscribeOper", return_value=_SubscribeOper()), patch.object(
with patch.object(module, "get_chain_subscribe_port", return_value=_SubscribeOper()), patch.object(
module,
"eventmanager",
_EventManager(),
@@ -3500,7 +3508,7 @@ class SubscribeDownloadFactsTest(TestCase):
def update(self, subscribe_id, payload):
updates.append(payload)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()):
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()):
snapshot = self.SubscribeChain()._SubscribeChain__record_subscribe_download_facts(
subscribe,
mediainfo=SimpleNamespace(title_year="下载事实剧 (2026)"),
@@ -3521,7 +3529,7 @@ class SubscribeDownloadFactsTest(TestCase):
def update(self, subscribe_id, payload):
updates.append(payload)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()):
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()):
snapshot = self.SubscribeChain()._SubscribeChain__record_subscribe_download_facts(
subscribe,
mediainfo=SimpleNamespace(title_year="下载事实剧 (2026)"),
@@ -3548,7 +3556,7 @@ class SubscribeDownloadFactsTest(TestCase):
def update(self, subscribe_id, payload):
updates.append(payload)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()):
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()):
snapshot = self.SubscribeChain()._SubscribeChain__record_subscribe_download_facts(
subscribe,
mediainfo=SimpleNamespace(title_year="下载事实剧 (2026)"),
@@ -3568,7 +3576,7 @@ class SubscribeDownloadFactsTest(TestCase):
def update(self, subscribe_id, payload):
updates.append(payload)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()):
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()):
snapshot = self.SubscribeChain()._SubscribeChain__record_subscribe_download_facts(
subscribe,
mediainfo=SimpleNamespace(title_year="下载事实剧 (2026)"),
@@ -3596,7 +3604,7 @@ class SubscribeDownloadFactsTest(TestCase):
episode_priority={"1": 60},
)
with patch.object(self.module, "SubscribeOper") as subscribe_oper_cls:
with patch.object(self.module, "get_chain_subscribe_port") as subscribe_oper_cls:
self.SubscribeChain()._SubscribeChain__record_subscribe_download_facts(
subscribe,
mediainfo=SimpleNamespace(title_year="下载事实剧 (2026)"),
@@ -3615,7 +3623,7 @@ class SubscribeDownloadFactsTest(TestCase):
def update(self, subscribe_id, payload):
updates.append(payload)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()):
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()):
snapshot = self.SubscribeChain()._SubscribeChain__record_subscribe_download_facts(
subscribe,
mediainfo=SimpleNamespace(title_year="下载事实剧 (2026)"),
@@ -3659,7 +3667,7 @@ class SubscribeDownloadFactsTest(TestCase):
def update(self, subscribe_id, payload):
updates.append(payload)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()), \
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()), \
patch.object(self.SubscribeChain, "_SubscribeChain__finish_subscribe"):
self.SubscribeChain().finish_subscribe_or_not(
subscribe=subscribe,
@@ -3695,7 +3703,7 @@ class SubscribeDownloadFactsTest(TestCase):
download.meta_info = SimpleNamespace(episode_list=[], season_list=[])
chain = self.SubscribeChain()
with patch.object(self.module, "SubscribeOper") as subscribe_oper_cls, \
with patch.object(self.module, "get_chain_subscribe_port") as subscribe_oper_cls, \
patch.object(chain, "_SubscribeChain__refresh_subscribe_progress_with_no_exists") as refresh_mock, \
patch.object(chain, "_SubscribeChain__finish_subscribe"):
subscribe_oper = subscribe_oper_cls.return_value
@@ -3732,7 +3740,7 @@ class SubscribeDownloadFactsTest(TestCase):
download.meta_info = SimpleNamespace(episode_list=[], season_list=[])
chain = self.SubscribeChain()
with patch.object(self.module, "SubscribeOper") as subscribe_oper_cls, \
with patch.object(self.module, "get_chain_subscribe_port") as subscribe_oper_cls, \
patch.object(chain, "_SubscribeChain__refresh_subscribe_progress_with_no_exists") as refresh_mock, \
patch.object(chain, "_SubscribeChain__finish_subscribe"):
subscribe_oper = subscribe_oper_cls.return_value
@@ -3779,7 +3787,7 @@ class SubscribeDownloadFactsTest(TestCase):
def finish_probe(subscribe, **_kwargs):
finished.append(subscribe.current_priority)
with patch.object(self.module, "SubscribeOper", return_value=_SubscribeOper()), \
with patch.object(self.module, "get_chain_subscribe_port", return_value=_SubscribeOper()), \
patch.object(chain, "_SubscribeChain__finish_subscribe", side_effect=finish_probe):
chain.finish_subscribe_or_not(
subscribe=subscribe,
+2 -2
View File
@@ -93,7 +93,7 @@ def test_subscribe_files_info_merges_multiple_mediaservers():
media_chain.recognize_media.return_value = mediainfo
chain = SubscribeChain()
with patch("app.chain.subscribe.DownloadHistoryOper") as download_oper, \
with patch("app.chain.subscribe.get_chain_download_history_port") as download_oper, \
patch("app.chain.subscribe.MediaChain", return_value=media_chain), \
patch.object(chain, "media_files", return_value=None), \
patch.object(chain, "media_exists", side_effect=_media_exists_side_effect), \
@@ -139,7 +139,7 @@ def test_subscribe_files_info_uses_season_zero_for_tv():
media_chain.recognize_media.return_value = mediainfo
chain = SubscribeChain()
with patch("app.chain.subscribe.DownloadHistoryOper") as download_oper, \
with patch("app.chain.subscribe.get_chain_download_history_port") as download_oper, \
patch("app.chain.subscribe.MediaChain", return_value=media_chain), \
patch.object(chain, "media_files", return_value=None), \
patch.object(chain, "media_exists", side_effect=_media_exists_side_effect), \
+1 -1
View File
@@ -507,7 +507,7 @@ def test_subscribe_chain_exists_forwards_episode_group():
media = _media("eg-1")
meta = SimpleNamespace(begin_season=1)
with patch("app.chain.subscribe.SubscribeOper") as subscribe_oper_cls:
with patch("app.chain.subscribe.get_chain_subscribe_port") as subscribe_oper_cls:
subscribe_oper_cls.return_value.exists.return_value = True
assert SubscribeChain.exists(media, meta) is True
+4 -4
View File
@@ -75,7 +75,7 @@ def test_new_subscribe_search_keeps_state_when_recently_created(monkeypatch) ->
"""
_SubscribeOper.subscribe = _new_subscribe(datetime.now())
_SubscribeOper.updates = []
monkeypatch.setattr(subscribe_module, "SubscribeOper", _SubscribeOper)
monkeypatch.setattr(subscribe_module, "get_chain_subscribe_port", _SubscribeOper)
media_chain_class = Mock()
with patch.object(subscribe_module, "MediaChain", media_chain_class):
@@ -92,7 +92,7 @@ def test_new_subscribe_search_marks_state_after_attempt(monkeypatch) -> None:
"""
_SubscribeOper.subscribe = _new_subscribe(datetime.now() - timedelta(minutes=2))
_SubscribeOper.updates = []
monkeypatch.setattr(subscribe_module, "SubscribeOper", _SubscribeOper)
monkeypatch.setattr(subscribe_module, "get_chain_subscribe_port", _SubscribeOper)
media_chain = Mock()
media_chain.recognize_media.return_value = None
@@ -117,7 +117,7 @@ def test_targeted_batch_searches_all_ids_without_state_scan(monkeypatch) -> None
subscribe_oper.get.side_effect = subscribes.get
monkeypatch.setattr(
subscribe_module,
"SubscribeOper",
"get_chain_subscribe_port",
lambda: subscribe_oper,
)
media_chain = Mock()
@@ -136,7 +136,7 @@ def test_subscribe_search_aborts_when_lock_times_out(monkeypatch) -> None:
"""订阅搜索锁超时后必须中止,不能在无锁状态下继续访问订阅。"""
monkeypatch.setattr(SubscribeChain, "_rlock", _TimedOutLock())
subscribe_oper = Mock()
monkeypatch.setattr(subscribe_module, "SubscribeOper", subscribe_oper)
monkeypatch.setattr(subscribe_module, "get_chain_subscribe_port", subscribe_oper)
progress = Mock()
chain = object.__new__(SubscribeChain)