mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-10-30 03:48:03 +08:00
240 lines
7.9 KiB
Python
240 lines
7.9 KiB
Python
"""
|
|
验证音乐整理计划中的分类决策。
|
|
"""
|
|
|
|
from app.chain.media import MediaChain
|
|
from app.chain.transfer.filter import FileFilterMixin
|
|
from app.domain.context import MusicInfo
|
|
from app.domain.meta.metamusic import MetaMusic
|
|
from app.schemas.category import ClassificationResult, ClassificationSelection
|
|
from app.schemas.file import FileItem
|
|
|
|
|
|
def test_album_context_preserves_classification_and_remote_music_facts(
|
|
tmp_path,
|
|
monkeypatch,
|
|
) -> None:
|
|
"""
|
|
目录专辑匹配重建曲目时应保留分类事实,并隔离缓存中的可变结果。
|
|
"""
|
|
file_path = tmp_path / "album" / "01-track.flac"
|
|
classification = ClassificationResult(
|
|
recommended=ClassificationSelection(
|
|
category_id="live",
|
|
category_path=["音乐", "现场"],
|
|
rule_id="music-live",
|
|
source="automatic",
|
|
),
|
|
effective=ClassificationSelection(
|
|
category_id="favorites",
|
|
category_path=["音乐", "收藏"],
|
|
rule_id="music-live",
|
|
source="subscription",
|
|
),
|
|
labels=["现场", "高解析"],
|
|
policy_revision=12,
|
|
state="complete",
|
|
)
|
|
matched_info = MusicInfo(
|
|
media_source="musicbrainz",
|
|
media_id="recording-1",
|
|
title="Remote title",
|
|
artists=["Remote artist"],
|
|
artist_ids=["artist-1"],
|
|
album="Remote album",
|
|
album_artist="Remote album artist",
|
|
album_id="release-group-1",
|
|
album_type="Album",
|
|
secondary_types=["Live", "Compilation"],
|
|
year=2024,
|
|
release_date="2024-05-01",
|
|
release_status="Official",
|
|
disc_number=1,
|
|
track_number=1,
|
|
total_tracks=10,
|
|
duration=1,
|
|
audio_format="MP3",
|
|
audio_lossless=False,
|
|
bit_depth=16,
|
|
sample_rate=44100,
|
|
bitrate=320000,
|
|
library_category="音乐/收藏",
|
|
metadata_category="Album / Live / Compilation",
|
|
classification=classification,
|
|
genres=["Rock"],
|
|
tags=["concert", "hi-res"],
|
|
artist_country="GB",
|
|
names=["Remote title", "远端曲名"],
|
|
detail_link="https://example.test/recording-1",
|
|
listen_count=42,
|
|
raw_data={"release": {"secondary_types": ["Live"]}},
|
|
)
|
|
local_meta = MetaMusic(
|
|
title="Remote title",
|
|
duration=321,
|
|
audio_format="FLAC",
|
|
audio_lossless=True,
|
|
bit_depth=24,
|
|
sample_rate=96000,
|
|
bitrate=2304000,
|
|
)
|
|
file_item = FileItem(
|
|
storage="local",
|
|
path=str(file_path),
|
|
type="file",
|
|
name=file_path.name,
|
|
basename=file_path.stem,
|
|
extension="flac",
|
|
)
|
|
monkeypatch.setattr(
|
|
MediaChain,
|
|
"recognize_music_album_directory",
|
|
lambda _self, _directory, **_kwargs: {str(file_path.resolve()): matched_info},
|
|
)
|
|
|
|
merged_meta, merged_info = FileFilterMixin._match_music_album_context(
|
|
file_item,
|
|
file_path,
|
|
local_meta,
|
|
)
|
|
|
|
assert merged_info is not None
|
|
assert merged_info.classification == classification
|
|
assert merged_info.classification is not classification
|
|
assert merged_info.classification.recommended is not classification.recommended
|
|
assert merged_info.classification.effective is not classification.effective
|
|
assert merged_info.classification.recommended.category_path == ["音乐", "现场"]
|
|
assert merged_info.classification.effective.category_path == ["音乐", "收藏"]
|
|
assert merged_info.classification.labels == ["现场", "高解析"]
|
|
assert merged_info.category == merged_info.library_category == "音乐/收藏"
|
|
assert merged_info.metadata_category == "Album / Live / Compilation"
|
|
assert merged_info.secondary_types == ["Live", "Compilation"]
|
|
assert merged_info.tags == ["concert", "hi-res"]
|
|
assert merged_info.genres == ["Rock"]
|
|
assert merged_info.release_status == "Official"
|
|
assert merged_info.artist_country == "GB"
|
|
assert merged_info.names == ["Remote title", "远端曲名"]
|
|
|
|
assert merged_meta.duration == merged_info.duration == 321
|
|
assert merged_meta.audio_format == merged_info.audio_format == "FLAC"
|
|
assert merged_info.audio_lossless is True
|
|
assert merged_info.bit_depth == 24
|
|
assert merged_info.sample_rate == 96000
|
|
assert merged_info.bitrate == 2304000
|
|
|
|
merged_info.classification.recommended.category_path.append("追加")
|
|
merged_info.classification.labels.append("新标签")
|
|
merged_info.secondary_types.append("Soundtrack")
|
|
merged_info.tags.append("new-tag")
|
|
merged_info.raw_data["release"]["secondary_types"].append("Remix")
|
|
|
|
assert classification.recommended.category_path == ["音乐", "现场"]
|
|
assert classification.labels == ["现场", "高解析"]
|
|
assert matched_info.secondary_types == ["Live", "Compilation"]
|
|
assert matched_info.tags == ["concert", "hi-res"]
|
|
assert matched_info.raw_data == {"release": {"secondary_types": ["Live"]}}
|
|
|
|
|
|
def test_album_context_rejects_candidate_conflicting_with_file_tags(
|
|
tmp_path,
|
|
monkeypatch,
|
|
) -> None:
|
|
"""
|
|
目录级匹配仍须核验逐文件明确的发行年份,不能用普通年份规则绕过冲突。
|
|
"""
|
|
file_path = tmp_path / "Speak Now" / "02 - Sparks Fly.flac"
|
|
local_meta = MetaMusic(
|
|
title="Sparks Fly",
|
|
artists=["Taylor Swift"],
|
|
album="Speak Now",
|
|
year=2010,
|
|
release_year=2010,
|
|
)
|
|
wrong_release = MusicInfo(
|
|
media_source="musicbrainz",
|
|
media_id="wrong-release-recording",
|
|
title="Sparks Fly",
|
|
artists=["Taylor Swift"],
|
|
album="Speak Now",
|
|
year=2025,
|
|
release_year=2025,
|
|
)
|
|
file_item = FileItem(
|
|
storage="local",
|
|
path=str(file_path),
|
|
type="file",
|
|
name=file_path.name,
|
|
basename=file_path.stem,
|
|
extension="flac",
|
|
)
|
|
monkeypatch.setattr(
|
|
MediaChain,
|
|
"recognize_music_album_directory",
|
|
lambda _self, _directory, **_kwargs: {str(file_path.resolve()): wrong_release},
|
|
)
|
|
|
|
returned_meta, returned_info = FileFilterMixin._match_music_album_context(
|
|
file_item,
|
|
file_path,
|
|
local_meta,
|
|
)
|
|
|
|
assert returned_meta is local_meta
|
|
assert returned_info is None
|
|
|
|
|
|
def test_album_context_preserves_local_release_track_position(
|
|
tmp_path,
|
|
monkeypatch,
|
|
) -> None:
|
|
"""
|
|
Recording 的其它发行版曲序不得覆盖当前文件的本地曲序。
|
|
"""
|
|
file_path = tmp_path / "Speak Now (Taylor's Version)" / "20 - Castles Crumbling.flac"
|
|
local_meta = MetaMusic(
|
|
title="Castles Crumbling (Taylor's Version)",
|
|
artists=["Taylor Swift", "Hayley Williams"],
|
|
album="Speak Now (Taylor's Version)",
|
|
year=2023,
|
|
disc_number=2,
|
|
track_number=20,
|
|
total_tracks=22,
|
|
)
|
|
matched_info = MusicInfo(
|
|
media_source="musicbrainz",
|
|
media_id="recording-castles-crumbling",
|
|
title="Castles Crumbling (Taylor's Version)",
|
|
artists=["Taylor Swift", "Hayley Williams"],
|
|
album="Speak Now (Taylor's Version)",
|
|
album_artist="Taylor Swift",
|
|
album_type="Album",
|
|
year=2023,
|
|
disc_number=1,
|
|
track_number=6,
|
|
total_tracks=6,
|
|
)
|
|
file_item = FileItem(
|
|
storage="local",
|
|
path=str(file_path),
|
|
type="file",
|
|
name=file_path.name,
|
|
basename=file_path.stem,
|
|
extension="flac",
|
|
)
|
|
monkeypatch.setattr(
|
|
MediaChain,
|
|
"recognize_music_album_directory",
|
|
lambda _self, _directory, **_kwargs: {str(file_path.resolve()): matched_info},
|
|
)
|
|
|
|
merged_meta, merged_info = FileFilterMixin._match_music_album_context(
|
|
file_item,
|
|
file_path,
|
|
local_meta,
|
|
)
|
|
|
|
assert merged_info is not None
|
|
assert merged_meta.disc_number == merged_info.disc_number == 2
|
|
assert merged_meta.track_number == merged_info.track_number == 20
|
|
assert merged_meta.total_tracks == merged_info.total_tracks == 22
|