Prefer alias if import languages not defined

This commit is contained in:
asardaes 2025-10-22 11:14:30 -06:00
parent 040b2dd940
commit c087851770
3 changed files with 75 additions and 10 deletions

View file

@ -16,6 +16,7 @@
from __future__ import annotations from __future__ import annotations
import itertools
import traceback import traceback
from copy import deepcopy from copy import deepcopy
from typing import TYPE_CHECKING, Any, Iterable, Sequence from typing import TYPE_CHECKING, Any, Iterable, Sequence
@ -24,6 +25,7 @@ import mediafile
import musicbrainzngs import musicbrainzngs
from typing_extensions import override from typing_extensions import override
from beets import config
from beets.autotag.distance import Distance, distance from beets.autotag.distance import Distance, distance
from beets.autotag.hooks import AlbumInfo from beets.autotag.hooks import AlbumInfo
from beets.autotag.match import assign_items from beets.autotag.match import assign_items
@ -34,6 +36,7 @@ from beetsplug.musicbrainz import (
MusicBrainzAPIError, MusicBrainzAPIError,
MusicBrainzPlugin, MusicBrainzPlugin,
_merge_pseudo_and_actual_album, _merge_pseudo_and_actual_album,
_preferred_alias,
) )
if TYPE_CHECKING: if TYPE_CHECKING:
@ -143,12 +146,13 @@ class MusicBrainzPseudoReleasePlugin(MusicBrainzPlugin):
try: try:
raw_pseudo_release = self._release_getter( raw_pseudo_release = self._release_getter(
album_id, RELEASE_INCLUDES album_id, RELEASE_INCLUDES
) )["release"]
pseudo_release = super().album_info( pseudo_release = super().album_info(raw_pseudo_release)
raw_pseudo_release["release"]
)
if self.config["custom_tags_only"].get(bool): if self.config["custom_tags_only"].get(bool):
self._replace_artist_with_alias(
raw_pseudo_release, pseudo_release
)
self._add_custom_tags(official_release, pseudo_release) self._add_custom_tags(official_release, pseudo_release)
return official_release return official_release
else: else:
@ -212,6 +216,41 @@ class MusicBrainzPseudoReleasePlugin(MusicBrainzPlugin):
else: else:
return None return None
def _replace_artist_with_alias(
self,
raw_pseudo_release: JSONDict,
pseudo_release: AlbumInfo,
):
"""Use the pseudo-release's language to search for artist
alias if the user hasn't configured import languages."""
if len(config["import"]["languages"].as_str_seq()) > 0:
return
lang = raw_pseudo_release.get("text-representation", {}).get("language")
artist_credits = raw_pseudo_release.get("release-group", {}).get(
"artist-credit", []
)
aliases = [
artist_credit.get("artist", {}).get("alias-list", [])
for artist_credit in artist_credits
]
if lang and len(lang) >= 2 and len(aliases) > 0:
locale = lang[0:2]
aliases_flattened = list(itertools.chain.from_iterable(aliases))
self._log.debug(
"Using locale '{0}' to search aliases {1}",
locale,
aliases_flattened,
)
if alias_dict := _preferred_alias(aliases_flattened, [locale]):
if alias := alias_dict.get("alias"):
self._log.debug("Got alias '{0}'", alias)
pseudo_release.artist = alias
for track in pseudo_release.tracks:
track.artist = alias
def _add_custom_tags( def _add_custom_tags(
self, self,
official_release: AlbumInfo, official_release: AlbumInfo,

View file

@ -118,13 +118,15 @@ BROWSE_CHUNKSIZE = 100
BROWSE_MAXTRACKS = 500 BROWSE_MAXTRACKS = 500
def _preferred_alias(aliases: list[JSONDict]): def _preferred_alias(
"""Given an list of alias structures for an artist credit, select aliases: list[JSONDict], languages: list[str] | None = None
and return the user's preferred alias alias or None if no matching ) -> JSONDict | None:
"""Given a list of alias structures for an artist credit, select
and return the user's preferred alias or None if no matching
alias is found. alias is found.
""" """
if not aliases: if not aliases:
return return None
# Only consider aliases that have locales set. # Only consider aliases that have locales set.
valid_aliases = [a for a in aliases if "locale" in a] valid_aliases = [a for a in aliases if "locale" in a]
@ -134,7 +136,10 @@ def _preferred_alias(aliases: list[JSONDict]):
ignored_alias_types = [a.lower() for a in ignored_alias_types] ignored_alias_types = [a.lower() for a in ignored_alias_types]
# Search configured locales in order. # Search configured locales in order.
for locale in config["import"]["languages"].as_str_seq(): if languages is None:
languages = config["import"]["languages"].as_str_seq()
for locale in languages:
# Find matching primary aliases for this locale that are not # Find matching primary aliases for this locale that are not
# being ignored # being ignored
matches = [] matches = []
@ -152,6 +157,8 @@ def _preferred_alias(aliases: list[JSONDict]):
return matches[0] return matches[0]
return None
def _multi_artist_credit( def _multi_artist_credit(
credit: list[JSONDict], include_join_phrase: bool credit: list[JSONDict], include_join_phrase: bool

View file

@ -3,6 +3,7 @@ import pathlib
import pytest import pytest
from beets import config
from beets.autotag import AlbumMatch from beets.autotag import AlbumMatch
from beets.autotag.distance import Distance from beets.autotag.distance import Distance
from beets.autotag.hooks import AlbumInfo, TrackInfo from beets.autotag.hooks import AlbumInfo, TrackInfo
@ -230,7 +231,6 @@ class TestMBPseudoPluginCustomTagsOnly(PluginMixin):
@pytest.fixture(scope="class") @pytest.fixture(scope="class")
def mbpseudo_plugin(self) -> MusicBrainzPseudoReleasePlugin: def mbpseudo_plugin(self) -> MusicBrainzPseudoReleasePlugin:
self.config["import"]["languages"] = ["en", "jp"]
self.config[self.plugin]["scripts"] = ["Latn"] self.config[self.plugin]["scripts"] = ["Latn"]
self.config[self.plugin]["custom_tags_only"] = True self.config[self.plugin]["custom_tags_only"] = True
return MusicBrainzPseudoReleasePlugin() return MusicBrainzPseudoReleasePlugin()
@ -255,6 +255,25 @@ class TestMBPseudoPluginCustomTagsOnly(PluginMixin):
official_release: JSONDict, official_release: JSONDict,
pseudo_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 = ( mbpseudo_plugin._release_getter = (
lambda album_id, includes: pseudo_release lambda album_id, includes: pseudo_release
) )