mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 15:38:19 +08:00
refactor backend module architecture
This commit is contained in:
+26
-25
@@ -5,10 +5,11 @@ from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from app.core.metainfo import MetaInfo, MetaInfoPath, find_metainfo
|
||||
from app.core.meta import MetaBase, MetaMusic
|
||||
from app.core.meta.metaanime import MetaAnime
|
||||
from app.helper.torrent import TorrentHelper
|
||||
from app.domain.metainfo import MetaInfo, MetaInfoPath, find_metainfo
|
||||
from app.domain.meta.metabase import MetaBase
|
||||
from app.domain.meta.metamusic import MetaMusic
|
||||
from app.domain.meta.metaanime import MetaAnime
|
||||
from app.services.torrent import TorrentHelper
|
||||
from app.schemas.types import MediaSource, MediaType
|
||||
from tests.cases.meta import meta_cases
|
||||
|
||||
@@ -161,7 +162,7 @@ def test_torrent_title_match_ignores_question_mark_variants():
|
||||
|
||||
def test_python_metainfo_fallback_preserves_xxx_movie_title():
|
||||
"""Python 兜底解析不应删除合法 xXx 片名。"""
|
||||
with patch("app.core.metainfo.rust_accel.parse_metainfo", return_value=None):
|
||||
with patch("app.infrastructure.rust.parse_metainfo", return_value=None):
|
||||
meta = MetaInfo("xXx 2002 1080p AMZN WEB-DL H.264 DDP 5.1-FROGWeb")
|
||||
|
||||
assert meta.en_name == "Xxx"
|
||||
@@ -173,7 +174,7 @@ def test_python_metainfo_fallback_preserves_xxx_movie_title():
|
||||
|
||||
def test_python_metainfo_fallback_recognizes_eac3_audio_codec():
|
||||
"""Python 兜底解析应识别 EAC3 及其声道信息。"""
|
||||
with patch("app.core.metainfo.rust_accel.parse_metainfo", return_value=None):
|
||||
with patch("app.infrastructure.rust.parse_metainfo", return_value=None):
|
||||
meta = MetaInfo("Test.Movie.2026.1080p.BluRay.x264.EAC3.5.1-GROUP")
|
||||
|
||||
assert meta.resource_pix == "1080p"
|
||||
@@ -215,7 +216,7 @@ def test_metainfo_preserves_all_resource_types(title, expected):
|
||||
@pytest.mark.parametrize(("title", "expected"), RESOURCE_TYPE_CASES)
|
||||
def test_python_metainfo_preserves_all_resource_types(title, expected):
|
||||
"""Python 兜底解析应按顺序保留并去重所有受支持的资源类型。"""
|
||||
with patch("app.core.metainfo.rust_accel.parse_metainfo", return_value=None):
|
||||
with patch("app.infrastructure.rust.parse_metainfo", return_value=None):
|
||||
meta = MetaInfo(title)
|
||||
|
||||
assert meta.resource_type == expected
|
||||
@@ -276,7 +277,7 @@ def test_metainfo_music_round_trip_preserves_fields():
|
||||
|
||||
def test_python_subtitle_episode_range_fin_with_chinese_season():
|
||||
"""Python 兜底解析应识别副标题中 [01-26Fin] 格式的集数范围(#6103)。"""
|
||||
with patch("app.core.metainfo.rust_accel.parse_metainfo", return_value=None):
|
||||
with patch("app.infrastructure.rust.parse_metainfo", return_value=None):
|
||||
meta = MetaInfo(
|
||||
title="JoJos Bizarre Adventure S01 2012 1080i BluRay x264 FLAC 2.0-AnimeF@ADE",
|
||||
subtitle="JOJO的奇妙冒险 第一季 / JoJo's Bizarre Adventure [01-26Fin] [简繁字幕]",
|
||||
@@ -305,7 +306,7 @@ def test_subtitle_episode_range_fin_with_default_parser():
|
||||
|
||||
def test_python_subtitle_episode_range_fin_without_chinese_marker():
|
||||
"""副标题无中文季集标记时也应识别 [01-38Fin] 集数范围。"""
|
||||
with patch("app.core.metainfo.rust_accel.parse_metainfo", return_value=None):
|
||||
with patch("app.infrastructure.rust.parse_metainfo", return_value=None):
|
||||
meta = MetaInfo(
|
||||
title="Some Show S01 2022 1080p WEB-DL H264-GRP",
|
||||
subtitle="Some Show [01-38Fin]",
|
||||
@@ -318,7 +319,7 @@ def test_python_subtitle_episode_range_fin_without_chinese_marker():
|
||||
|
||||
def test_python_subtitle_episode_range_end_variant():
|
||||
"""END/完结 等完结标记变体同样应识别为集数范围。"""
|
||||
with patch("app.core.metainfo.rust_accel.parse_metainfo", return_value=None):
|
||||
with patch("app.infrastructure.rust.parse_metainfo", return_value=None):
|
||||
meta_end = MetaInfo(
|
||||
title="Some Show S01 2022 1080p WEB-DL H264-GRP",
|
||||
subtitle="Some Show 01-24 END",
|
||||
@@ -336,7 +337,7 @@ def test_python_subtitle_episode_range_end_variant():
|
||||
|
||||
def test_python_subtitle_year_range_not_treated_as_episodes():
|
||||
"""年份范围(如 2019-2020)不得误识别为集数。"""
|
||||
with patch("app.core.metainfo.rust_accel.parse_metainfo", return_value=None):
|
||||
with patch("app.infrastructure.rust.parse_metainfo", return_value=None):
|
||||
meta = MetaInfo(
|
||||
title="Some Collection 2020 1080p WEB-DL H264-GRP",
|
||||
subtitle="A Collection [2019-2020Fin]",
|
||||
@@ -349,7 +350,7 @@ def test_python_subtitle_year_range_not_treated_as_episodes():
|
||||
def test_python_subtitle_episode_range_fin_rejects_numeric_suffix():
|
||||
"""Python 兜底解析不得把带数字后缀的完结范围截断识别为集数。"""
|
||||
for subtitle in ("Some Show [01-26Fin]2", "Some Show 01-26Fin 2"):
|
||||
with patch("app.core.metainfo.rust_accel.parse_metainfo", return_value=None):
|
||||
with patch("app.infrastructure.rust.parse_metainfo", return_value=None):
|
||||
meta = MetaInfo(
|
||||
title="Some Show S01 2022 1080p WEB-DL H264-GRP",
|
||||
subtitle=subtitle,
|
||||
@@ -389,7 +390,7 @@ def test_custom_words_episode_offset_supports_multiplication_expression():
|
||||
r"Ha.Ha.Ha.Ha.Ha.2026.S06E([0-1][0-9]).Part1 => 哈哈哈哈哈 (2020){[tmdbid=112732;type=tv]} S06E\1.Part1 && S06 <> .Part1 >> 2*EP-1"
|
||||
]
|
||||
|
||||
with patch("app.core.metainfo.rust_accel.parse_metainfo", return_value=None):
|
||||
with patch("app.infrastructure.rust.parse_metainfo", return_value=None):
|
||||
meta = MetaInfo(
|
||||
title="Ha.Ha.Ha.Ha.Ha.2026.S06E03.Part1",
|
||||
custom_words=custom_words,
|
||||
@@ -407,7 +408,7 @@ def test_custom_words_episode_offset_supports_repeated_ep_expression():
|
||||
"""测试集数偏移表达式支持重复使用 EP 占位符。"""
|
||||
custom_words = ["旧名 => 新名 && 第 <> 集 >> EP+EP-1"]
|
||||
|
||||
with patch("app.core.metainfo.rust_accel.parse_metainfo", return_value=None):
|
||||
with patch("app.infrastructure.rust.parse_metainfo", return_value=None):
|
||||
meta = MetaInfo(title="旧名 第03集", custom_words=custom_words)
|
||||
|
||||
assert meta.name == "新名"
|
||||
@@ -419,7 +420,7 @@ def test_custom_words_episode_offset_rejects_implicit_ep_expression():
|
||||
"""测试集数偏移表达式不把 2EP 当作隐式乘法或字符串拼接。"""
|
||||
custom_words = ["旧名 => 新名 && 第 <> 集 >> 2EP"]
|
||||
|
||||
with patch("app.core.metainfo.rust_accel.parse_metainfo", return_value=None):
|
||||
with patch("app.infrastructure.rust.parse_metainfo", return_value=None):
|
||||
meta = MetaInfo(title="旧名 第03集", custom_words=custom_words)
|
||||
|
||||
assert meta.name == "新名"
|
||||
@@ -448,7 +449,7 @@ def test_custom_words_support_special_season_zero_parameter():
|
||||
"Test Show => 测试剧 {[tmdbid=12345;type=tv;s=0]}"
|
||||
]
|
||||
|
||||
with patch("app.core.metainfo.rust_accel.parse_metainfo", return_value=None):
|
||||
with patch("app.infrastructure.rust.parse_metainfo", return_value=None):
|
||||
meta = MetaInfo(title="Test Show 01", custom_words=custom_words)
|
||||
|
||||
assert meta.media_source == MediaSource.TMDB
|
||||
@@ -468,7 +469,7 @@ def test_find_metainfo_supports_episode_group_parameter():
|
||||
def test_find_metainfo_does_not_support_episode_group_alias():
|
||||
"""测试 e_group 不会被当作剧集组参数识别。"""
|
||||
group_id = "5ad0ec240e0a26303f00d84d"
|
||||
with patch("app.core.metainfo.rust_accel.find_metainfo", return_value=None):
|
||||
with patch("app.infrastructure.rust.find_metainfo", return_value=None):
|
||||
_, metainfo = find_metainfo(f"物语系列 {{[tmdbid=46195;type=tv;e_group={group_id};s=1]}}")
|
||||
assert metainfo["episode_group"] is None
|
||||
|
||||
@@ -482,7 +483,7 @@ def test_video_bit_extracted_for_video_title():
|
||||
|
||||
def test_special_season_zero_enables_whole_season_resource_parsing():
|
||||
"""只有 S00、没有集号的整季标题仍应识别后续编码信息。"""
|
||||
with patch("app.core.metainfo.rust_accel.parse_metainfo", return_value=None):
|
||||
with patch("app.infrastructure.rust.parse_metainfo", return_value=None):
|
||||
meta = MetaInfo(title="Demo Show S00 X265 AAC")
|
||||
|
||||
assert meta.begin_season == 0
|
||||
@@ -497,7 +498,7 @@ def test_anime_parser_preserves_numeric_special_season_zero():
|
||||
"anime_season": 0,
|
||||
"episode_number": "1",
|
||||
}
|
||||
with patch("app.core.meta.metaanime.anitopy.parse", return_value=parsed):
|
||||
with patch("app.domain.meta.metaanime.anitopy.parse", return_value=parsed):
|
||||
meta = MetaAnime(title="Demo Anime S00E01")
|
||||
|
||||
assert meta.begin_season == 0
|
||||
@@ -505,7 +506,7 @@ def test_anime_parser_preserves_numeric_special_season_zero():
|
||||
assert meta.type == MediaType.TV
|
||||
|
||||
parsed["anime_season"] = [0, "1"]
|
||||
with patch("app.core.meta.metaanime.anitopy.parse", return_value=parsed):
|
||||
with patch("app.domain.meta.metaanime.anitopy.parse", return_value=parsed):
|
||||
ranged_meta = MetaAnime(title="Demo Anime S00-S01")
|
||||
|
||||
assert ranged_meta.begin_season == 0
|
||||
@@ -525,9 +526,9 @@ def test_anime_parser_ignores_empty_and_invalid_season_values():
|
||||
"episode_number": "1",
|
||||
}
|
||||
|
||||
with patch("app.core.meta.metaanime.anitopy.parse", return_value=empty):
|
||||
with patch("app.domain.meta.metaanime.anitopy.parse", return_value=empty):
|
||||
empty_meta = MetaAnime(title="Demo Anime E01")
|
||||
with patch("app.core.meta.metaanime.anitopy.parse", return_value=invalid_list):
|
||||
with patch("app.domain.meta.metaanime.anitopy.parse", return_value=invalid_list):
|
||||
invalid_meta = MetaAnime(title="Demo Anime E01")
|
||||
|
||||
assert empty_meta.begin_season is None
|
||||
@@ -536,7 +537,7 @@ def test_anime_parser_ignores_empty_and_invalid_season_values():
|
||||
|
||||
def test_hdr_vivid_effect_extracted_for_video_title():
|
||||
"""测试合并写法 HDRVivid 可识别为资源效果。"""
|
||||
with patch("app.core.metainfo.rust_accel.parse_metainfo", return_value=None):
|
||||
with patch("app.infrastructure.rust.parse_metainfo", return_value=None):
|
||||
meta = MetaInfo(
|
||||
title="Never-Ending Summer 2026 S01E18-S01E19 2160p WEB-DL 50Fps "
|
||||
"HDRVivid H265 10bit AAC-XXWEB"
|
||||
@@ -559,7 +560,7 @@ def test_video_bit_extracted_for_anime_title():
|
||||
|
||||
def test_streaming_platform_word_kept_in_movie_title():
|
||||
"""测试正式片名中的流媒体平台词不会被预置清理规则移除。"""
|
||||
with patch("app.core.metainfo.rust_accel.parse_metainfo", return_value=None):
|
||||
with patch("app.infrastructure.rust.parse_metainfo", return_value=None):
|
||||
meta = MetaInfo(title="Amazon Forever 2004 1080p WEB-DL")
|
||||
assert meta.name == "Amazon Forever"
|
||||
assert meta.year == "2004"
|
||||
@@ -589,7 +590,7 @@ def test_custom_identifier_uses_source_specific_id_and_returns_unified_identity(
|
||||
def test_generic_media_identity_is_not_custom_identifier_syntax():
|
||||
"""通用身份字段不得因 Rust 扩展版本差异被自定义识别词解析器接收。"""
|
||||
with patch(
|
||||
"app.core.metainfo.rust_accel.find_metainfo",
|
||||
"app.infrastructure.rust.find_metainfo",
|
||||
side_effect=AssertionError("通用身份标签必须绕过 Rust 解析器"),
|
||||
):
|
||||
_, metainfo = find_metainfo(
|
||||
|
||||
Reference in New Issue
Block a user