mirror of
https://github.com/beetbox/beets.git
synced 2025-12-06 16:42:42 +01:00
378 lines
13 KiB
Python
378 lines
13 KiB
Python
import json
|
|
import pathlib
|
|
from copy import deepcopy
|
|
|
|
import pytest
|
|
|
|
from beets import config
|
|
from beets.autotag import AlbumMatch
|
|
from beets.autotag.distance import Distance
|
|
from beets.autotag.hooks import AlbumInfo, TrackInfo
|
|
from beets.library import Item
|
|
from beets.test.helper import PluginMixin
|
|
from beetsplug._typing import JSONDict
|
|
from beetsplug.mbpseudo import (
|
|
_STATUS_PSEUDO,
|
|
MultiPseudoAlbumInfo,
|
|
MusicBrainzPseudoReleasePlugin,
|
|
PseudoAlbumInfo,
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def official_release_info() -> AlbumInfo:
|
|
return AlbumInfo(
|
|
tracks=[TrackInfo(title="百花繚乱")],
|
|
album_id="official",
|
|
album="百花繚乱",
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def pseudo_release_info() -> AlbumInfo:
|
|
return AlbumInfo(
|
|
tracks=[TrackInfo(title="In Bloom")],
|
|
album_id="pseudo",
|
|
album="In Bloom",
|
|
)
|
|
|
|
|
|
class TestPseudoAlbumInfo:
|
|
def test_album_id_always_from_pseudo(
|
|
self, official_release_info: AlbumInfo, pseudo_release_info: AlbumInfo
|
|
):
|
|
info = PseudoAlbumInfo(pseudo_release_info, official_release_info)
|
|
info.use_official_as_ref()
|
|
assert info.album_id == "pseudo"
|
|
|
|
def test_get_attr_from_pseudo(
|
|
self, official_release_info: AlbumInfo, pseudo_release_info: AlbumInfo
|
|
):
|
|
info = PseudoAlbumInfo(pseudo_release_info, official_release_info)
|
|
info.use_pseudo_as_ref()
|
|
assert info.album == "In Bloom"
|
|
|
|
def test_get_attr_from_official(
|
|
self, official_release_info: AlbumInfo, pseudo_release_info: AlbumInfo
|
|
):
|
|
info = PseudoAlbumInfo(pseudo_release_info, official_release_info)
|
|
info.use_official_as_ref()
|
|
assert info.album == info.get_official_release().album
|
|
|
|
def test_determine_best_ref(
|
|
self, official_release_info: AlbumInfo, pseudo_release_info: AlbumInfo
|
|
):
|
|
info = PseudoAlbumInfo(
|
|
pseudo_release_info, official_release_info, data_source="test"
|
|
)
|
|
item = Item()
|
|
item["title"] = "百花繚乱"
|
|
|
|
assert info.determine_best_ref([item]) == "official"
|
|
|
|
info.use_pseudo_as_ref()
|
|
assert info.data_source == "test"
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def rsrc_dir(pytestconfig: pytest.Config):
|
|
return pytestconfig.rootpath / "test" / "rsrc" / "mbpseudo"
|
|
|
|
|
|
class TestMBPseudoPlugin(PluginMixin):
|
|
plugin = "mbpseudo"
|
|
|
|
@pytest.fixture(scope="class")
|
|
def plugin_config(self):
|
|
return {"scripts": ["Latn", "Dummy"]}
|
|
|
|
@pytest.fixture(scope="class")
|
|
def mbpseudo_plugin(self, plugin_config) -> MusicBrainzPseudoReleasePlugin:
|
|
self.config[self.plugin].set(plugin_config)
|
|
return MusicBrainzPseudoReleasePlugin()
|
|
|
|
@pytest.fixture
|
|
def official_release(self, rsrc_dir: pathlib.Path) -> JSONDict:
|
|
info_json = (rsrc_dir / "official_release.json").read_text(
|
|
encoding="utf-8"
|
|
)
|
|
return json.loads(info_json)
|
|
|
|
@pytest.fixture
|
|
def pseudo_release(self, rsrc_dir: pathlib.Path) -> JSONDict:
|
|
info_json = (rsrc_dir / "pseudo_release.json").read_text(
|
|
encoding="utf-8"
|
|
)
|
|
return json.loads(info_json)
|
|
|
|
def test_scripts_init(
|
|
self, mbpseudo_plugin: MusicBrainzPseudoReleasePlugin
|
|
):
|
|
assert mbpseudo_plugin._scripts == ["Latn", "Dummy"]
|
|
|
|
@pytest.mark.parametrize(
|
|
"album_id",
|
|
[
|
|
"a5ce1d11-2e32-45a4-b37f-c1589d46b103",
|
|
"-5ce1d11-2e32-45a4-b37f-c1589d46b103",
|
|
],
|
|
)
|
|
def test_extract_id_uses_music_brainz_pattern(
|
|
self,
|
|
mbpseudo_plugin: MusicBrainzPseudoReleasePlugin,
|
|
album_id: str,
|
|
):
|
|
if album_id.startswith("-"):
|
|
assert mbpseudo_plugin._extract_id(album_id) is None
|
|
else:
|
|
assert mbpseudo_plugin._extract_id(album_id) == album_id
|
|
|
|
def test_reimport_logic(
|
|
self,
|
|
mbpseudo_plugin: MusicBrainzPseudoReleasePlugin,
|
|
official_release_info: AlbumInfo,
|
|
pseudo_release_info: AlbumInfo,
|
|
):
|
|
pseudo_info = PseudoAlbumInfo(
|
|
pseudo_release_info, official_release_info
|
|
)
|
|
|
|
item = Item()
|
|
item["title"] = "百花繚乱"
|
|
|
|
# if items don't have mb_*, they are not modified
|
|
mbpseudo_plugin.before_album_info_emitted([item], pseudo_info)
|
|
assert pseudo_info.album == item.title
|
|
|
|
pseudo_info.use_pseudo_as_ref()
|
|
assert pseudo_info.album == "In Bloom"
|
|
|
|
item["mb_albumid"] = "mb_aid"
|
|
item["mb_trackid"] = "mb_tid"
|
|
assert item.get("mb_albumid") == "mb_aid"
|
|
assert item.get("mb_trackid") == "mb_tid"
|
|
|
|
# if items have mb_*, they are deleted
|
|
mbpseudo_plugin.before_album_info_emitted([item], pseudo_info)
|
|
assert pseudo_info.album == item.title
|
|
assert item.get("mb_albumid") == ""
|
|
assert item.get("mb_trackid") == ""
|
|
|
|
def test_album_info_for_pseudo_release(
|
|
self,
|
|
mbpseudo_plugin: MusicBrainzPseudoReleasePlugin,
|
|
pseudo_release: JSONDict,
|
|
):
|
|
album_info = mbpseudo_plugin.album_info(pseudo_release["release"])
|
|
assert isinstance(album_info, PseudoAlbumInfo)
|
|
assert album_info.data_source == "MusicBrainzPseudoRelease"
|
|
assert album_info.albumstatus == _STATUS_PSEUDO
|
|
|
|
@pytest.mark.parametrize(
|
|
"json_key",
|
|
[
|
|
"type",
|
|
"direction",
|
|
"release",
|
|
],
|
|
)
|
|
def test_interception_skip_when_rel_values_dont_match(
|
|
self,
|
|
mbpseudo_plugin: MusicBrainzPseudoReleasePlugin,
|
|
official_release: JSONDict,
|
|
json_key: str,
|
|
):
|
|
for r in official_release["release"]["release-relation-list"]:
|
|
del r[json_key]
|
|
|
|
album_info = mbpseudo_plugin.album_info(official_release["release"])
|
|
assert not isinstance(album_info, PseudoAlbumInfo)
|
|
assert album_info.data_source == "MusicBrainzPseudoRelease"
|
|
|
|
def test_interception_skip_when_script_doesnt_match(
|
|
self,
|
|
mbpseudo_plugin: MusicBrainzPseudoReleasePlugin,
|
|
official_release: JSONDict,
|
|
):
|
|
for r in official_release["release"]["release-relation-list"]:
|
|
r["release"]["text-representation"]["script"] = "Null"
|
|
|
|
album_info = mbpseudo_plugin.album_info(official_release["release"])
|
|
assert not isinstance(album_info, PseudoAlbumInfo)
|
|
assert album_info.data_source == "MusicBrainzPseudoRelease"
|
|
|
|
def test_interception(
|
|
self,
|
|
mbpseudo_plugin: MusicBrainzPseudoReleasePlugin,
|
|
official_release: JSONDict,
|
|
pseudo_release: JSONDict,
|
|
):
|
|
mbpseudo_plugin._release_getter = (
|
|
lambda album_id, includes: pseudo_release
|
|
)
|
|
album_info = mbpseudo_plugin.album_info(official_release["release"])
|
|
assert isinstance(album_info, PseudoAlbumInfo)
|
|
assert album_info.data_source == "MusicBrainzPseudoRelease"
|
|
|
|
def test_final_adjustment_skip(
|
|
self,
|
|
mbpseudo_plugin: MusicBrainzPseudoReleasePlugin,
|
|
):
|
|
match = AlbumMatch(
|
|
distance=Distance(),
|
|
info=AlbumInfo(tracks=[], data_source="mb"),
|
|
mapping={},
|
|
extra_items=[],
|
|
extra_tracks=[],
|
|
)
|
|
|
|
mbpseudo_plugin._adjust_final_album_match(match)
|
|
assert match.info.data_source == "mb"
|
|
|
|
def test_final_adjustment(
|
|
self,
|
|
mbpseudo_plugin: MusicBrainzPseudoReleasePlugin,
|
|
official_release_info: AlbumInfo,
|
|
pseudo_release_info: AlbumInfo,
|
|
):
|
|
pseudo_album_info = PseudoAlbumInfo(
|
|
pseudo_release=pseudo_release_info,
|
|
official_release=official_release_info,
|
|
data_source=mbpseudo_plugin.data_source,
|
|
)
|
|
pseudo_album_info.use_official_as_ref()
|
|
|
|
item = Item()
|
|
item["title"] = "百花繚乱"
|
|
|
|
match = AlbumMatch(
|
|
distance=Distance(),
|
|
info=pseudo_album_info,
|
|
mapping={item: pseudo_album_info.tracks[0]},
|
|
extra_items=[],
|
|
extra_tracks=[],
|
|
)
|
|
|
|
mbpseudo_plugin._adjust_final_album_match(match)
|
|
|
|
assert match.info.data_source == "MusicBrainz"
|
|
assert match.info.album_id == "pseudo"
|
|
assert match.info.album == "In Bloom"
|
|
|
|
|
|
class TestMBPseudoPluginMultipleAllowed(PluginMixin):
|
|
plugin = "mbpseudo"
|
|
|
|
@pytest.fixture(scope="class")
|
|
def plugin_config(self):
|
|
return {"scripts": ["Latn", "Dummy"], "multiple_allowed": True}
|
|
|
|
@pytest.fixture(scope="class")
|
|
def mbpseudo_plugin(self, plugin_config) -> MusicBrainzPseudoReleasePlugin:
|
|
self.config[self.plugin].set(plugin_config)
|
|
config["import"]["languages"] = ["jp", "en"]
|
|
return MusicBrainzPseudoReleasePlugin()
|
|
|
|
@pytest.fixture(scope="class")
|
|
def official_release(self, rsrc_dir: pathlib.Path) -> JSONDict:
|
|
info_json = (rsrc_dir / "official_release.json").read_text(
|
|
encoding="utf-8"
|
|
)
|
|
return json.loads(info_json)
|
|
|
|
@pytest.fixture(scope="class")
|
|
def pseudo_release(self, rsrc_dir: pathlib.Path) -> JSONDict:
|
|
info_json = (rsrc_dir / "pseudo_release.json").read_text(
|
|
encoding="utf-8"
|
|
)
|
|
return json.loads(info_json)
|
|
|
|
def test_multiple_releases(
|
|
self,
|
|
mbpseudo_plugin: MusicBrainzPseudoReleasePlugin,
|
|
official_release: JSONDict,
|
|
pseudo_release: JSONDict,
|
|
):
|
|
def mock_release_getter(album_id: str, _) -> JSONDict:
|
|
if album_id == "dc3ee2df-0bc1-49eb-b8c4-34473d279a43":
|
|
return pseudo_release
|
|
else:
|
|
clone = deepcopy(pseudo_release)
|
|
clone["release"]["id"] = album_id
|
|
clone["release"]["text-representation"]["language"] = "jpn"
|
|
return clone
|
|
|
|
mbpseudo_plugin._release_getter = mock_release_getter
|
|
|
|
album_info = mbpseudo_plugin.album_info(official_release["release"])
|
|
assert isinstance(album_info, MultiPseudoAlbumInfo)
|
|
assert album_info.data_source == "MusicBrainzPseudoRelease"
|
|
assert len(album_info.unwrap()) == 2
|
|
assert (
|
|
album_info.unwrap()[0].album_id
|
|
== "dc3ee2df-mock-49eb-b8c4-34473d279a43"
|
|
)
|
|
assert (
|
|
album_info.unwrap()[1].album_id
|
|
== "dc3ee2df-0bc1-49eb-b8c4-34473d279a43"
|
|
)
|
|
|
|
|
|
class TestMBPseudoPluginCustomTagsOnly(PluginMixin):
|
|
plugin = "mbpseudo"
|
|
|
|
@pytest.fixture(scope="class")
|
|
def mbpseudo_plugin(self) -> MusicBrainzPseudoReleasePlugin:
|
|
self.config[self.plugin]["scripts"] = ["Latn"]
|
|
self.config[self.plugin]["custom_tags_only"] = True
|
|
return MusicBrainzPseudoReleasePlugin()
|
|
|
|
@pytest.fixture(scope="class")
|
|
def official_release(self, rsrc_dir: pathlib.Path) -> JSONDict:
|
|
info_json = (rsrc_dir / "official_release.json").read_text(
|
|
encoding="utf-8"
|
|
)
|
|
return json.loads(info_json)
|
|
|
|
@pytest.fixture(scope="class")
|
|
def pseudo_release(self, rsrc_dir: pathlib.Path) -> JSONDict:
|
|
info_json = (rsrc_dir / "pseudo_release.json").read_text(
|
|
encoding="utf-8"
|
|
)
|
|
return json.loads(info_json)
|
|
|
|
def test_custom_tags(
|
|
self,
|
|
mbpseudo_plugin: MusicBrainzPseudoReleasePlugin,
|
|
official_release: JSONDict,
|
|
pseudo_release: JSONDict,
|
|
):
|
|
config["import"]["languages"] = []
|
|
mbpseudo_plugin._release_getter = (
|
|
lambda album_id, includes: pseudo_release
|
|
)
|
|
album_info = mbpseudo_plugin.album_info(official_release["release"])
|
|
assert not isinstance(album_info, PseudoAlbumInfo)
|
|
assert album_info.data_source == "MusicBrainzPseudoRelease"
|
|
assert album_info["album_transl"] == "In Bloom"
|
|
assert album_info["album_artist_transl"] == "Lilas Ikuta"
|
|
assert album_info.tracks[0]["title_transl"] == "In Bloom"
|
|
assert album_info.tracks[0]["artist_transl"] == "Lilas Ikuta"
|
|
|
|
def test_custom_tags_with_import_languages(
|
|
self,
|
|
mbpseudo_plugin: MusicBrainzPseudoReleasePlugin,
|
|
official_release: JSONDict,
|
|
pseudo_release: JSONDict,
|
|
):
|
|
config["import"]["languages"] = ["en", "jp"]
|
|
mbpseudo_plugin._release_getter = (
|
|
lambda album_id, includes: pseudo_release
|
|
)
|
|
album_info = mbpseudo_plugin.album_info(official_release["release"])
|
|
assert not isinstance(album_info, PseudoAlbumInfo)
|
|
assert album_info.data_source == "MusicBrainzPseudoRelease"
|
|
assert album_info["album_transl"] == "In Bloom"
|
|
assert album_info["album_artist_transl"] == "Lilas Ikuta"
|
|
assert album_info.tracks[0]["title_transl"] == "In Bloom"
|
|
assert album_info.tracks[0]["artist_transl"] == "Lilas Ikuta"
|