musicbrainz: update patches

This commit is contained in:
Šarūnas Nejus 2025-02-17 23:29:36 +00:00
parent bef0bcbaa6
commit 0980c82959
No known key found for this signature in database
GPG key ID: DD28F6704DBE3435
3 changed files with 88 additions and 172 deletions

View file

@ -49,7 +49,7 @@ from mediafile import Image, MediaFile
import beets
import beets.plugins
from beets import autotag, importer, logging, util
from beets import importer, logging, util
from beets.autotag.hooks import AlbumInfo, TrackInfo
from beets.importer import ImportSession
from beets.library import Album, Item, Library
@ -791,40 +791,37 @@ class AutotagStub:
length = 2
def install(self):
self.mb_match_album = autotag.mb.match_album
self.mb_match_track = autotag.mb.match_track
self.mb_album_for_id = autotag.mb.album_for_id
self.mb_track_for_id = autotag.mb.track_for_id
autotag.mb.match_album = self.match_album
autotag.mb.match_track = self.match_track
autotag.mb.album_for_id = self.album_for_id
autotag.mb.track_for_id = self.track_for_id
self.patchers = [
patch("beets.plugins.album_for_id", lambda *_: None),
patch("beets.plugins.track_for_id", lambda *_: None),
patch("beets.plugins.candidates", self.candidates),
patch("beets.plugins.item_candidates", self.item_candidates),
]
for p in self.patchers:
p.start()
return self
def restore(self):
autotag.mb.match_album = self.mb_match_album
autotag.mb.match_track = self.mb_match_track
autotag.mb.album_for_id = self.mb_album_for_id
autotag.mb.track_for_id = self.mb_track_for_id
for p in self.patchers:
p.stop()
def match_album(self, albumartist, album, tracks, extra_tags):
def candidates(self, items, artist, album, va_likely, extra_tags=None):
if self.matching == self.IDENT:
yield self._make_album_match(albumartist, album, tracks)
yield self._make_album_match(artist, album, len(items))
elif self.matching == self.GOOD:
for i in range(self.length):
yield self._make_album_match(albumartist, album, tracks, i)
yield self._make_album_match(artist, album, len(items), i)
elif self.matching == self.BAD:
for i in range(self.length):
yield self._make_album_match(albumartist, album, tracks, i + 1)
yield self._make_album_match(artist, album, len(items), i + 1)
elif self.matching == self.MISSING:
yield self._make_album_match(albumartist, album, tracks, missing=1)
yield self._make_album_match(artist, album, len(items), missing=1)
def match_track(self, artist, title):
def item_candidates(self, item, artist, title):
yield TrackInfo(
title=title.replace("Tag", "Applied"),
track_id="trackid",
@ -834,12 +831,6 @@ class AutotagStub:
index=0,
)
def album_for_id(self, mbid):
return None
def track_for_id(self, mbid):
return None
def _make_track_match(self, artist, album, number):
return TrackInfo(
title="Applied Track %d" % number,

View file

@ -363,7 +363,7 @@ class ChangeRepresentation:
self.indent_header + f"Match ({dist_string(self.match.distance)}):"
)
if self.match.info.get("album"):
if isinstance(self.match.info, autotag.hooks.AlbumInfo):
# Matching an album - print that
artist_album_str = (
f"{self.match.info.artist}" + f" - {self.match.info.album}"

View file

@ -1061,26 +1061,22 @@ class InferAlbumDataTest(BeetsTestCase):
assert not self.items[0].comp
def match_album_mock(*args, **kwargs):
def album_candidates_mock(*args, **kwargs):
"""Create an AlbumInfo object for testing."""
track_info = TrackInfo(
title="new title",
track_id="trackid",
index=0,
)
album_info = AlbumInfo(
yield AlbumInfo(
artist="artist",
album="album",
tracks=[track_info],
tracks=[TrackInfo(title="new title", track_id="trackid", index=0)],
album_id="albumid",
artist_id="artistid",
flex="flex",
)
return iter([album_info])
@patch("beets.autotag.mb.match_album", Mock(side_effect=match_album_mock))
class ImportDuplicateAlbumTest(ImportTestCase):
@patch("beets.plugins.candidates", Mock(side_effect=album_candidates_mock))
class ImportDuplicateAlbumTest(PluginMixin, ImportTestCase):
plugin = "musicbrainz"
def setUp(self):
super().setUp()
@ -1186,20 +1182,16 @@ class ImportDuplicateAlbumTest(ImportTestCase):
return album
def match_track_mock(*args, **kwargs):
return iter(
[
TrackInfo(
def item_candidates_mock(*args, **kwargs):
yield TrackInfo(
artist="artist",
title="title",
track_id="new trackid",
index=0,
)
]
)
@patch("beets.autotag.mb.match_track", Mock(side_effect=match_track_mock))
@patch("beets.plugins.item_candidates", Mock(side_effect=item_candidates_mock))
class ImportDuplicateSingletonTest(ImportTestCase):
def setUp(self):
super().setUp()
@ -1633,7 +1625,7 @@ class ReimportTest(AutotagImportTestCase):
def test_reimported_album_not_preserves_flexattr(self):
self._setup_session()
assert self._album().data_source == "original_source"
self.importer.run()
assert self._album().data_source == "match_source"
@ -1657,6 +1649,7 @@ class ImportPretendTest(AutotagImportTestCase):
assert len(self.lib.albums()) == 0
return [line for line in logs if not line.startswith("Sending event:")]
assert self._album().data_source == "original_source"
def test_import_singletons_pretend(self):
assert self.__run(self.setup_singleton_importer(pretend=True)) == [
@ -1681,112 +1674,64 @@ class ImportPretendTest(AutotagImportTestCase):
assert self.__run(importer) == [f"No files imported from {empty_path}"]
# Helpers for ImportMusicBrainzIdTest.
def mocked_get_album_by_id(id_):
"""Return album candidate for the given id.
def mocked_get_release_by_id(
id_, includes=[], release_status=[], release_type=[]
):
"""Mimic musicbrainzngs.get_release_by_id, accepting only a restricted list
of MB ids (ID_RELEASE_0, ID_RELEASE_1). The returned dict differs only in
the release title and artist name, so that ID_RELEASE_0 is a closer match
to the items created by ImportHelper.prepare_album_for_import()."""
The two albums differ only in the release title and artist name, so that
ID_RELEASE_0 is a closer match to the items created by
ImportHelper.prepare_album_for_import().
"""
# Map IDs to (release title, artist), so the distances are different.
releases = {
ImportMusicBrainzIdTest.ID_RELEASE_0: ("VALID_RELEASE_0", "TAG ARTIST"),
ImportMusicBrainzIdTest.ID_RELEASE_1: (
"VALID_RELEASE_1",
"DISTANT_MATCH",
),
}
album, artist = {
ImportIdTest.ID_RELEASE_0: ("VALID_RELEASE_0", "TAG ARTIST"),
ImportIdTest.ID_RELEASE_1: ("VALID_RELEASE_1", "DISTANT_MATCH"),
}[id_]
return {
"release": {
"title": releases[id_][0],
"id": id_,
"medium-list": [
{
"track-list": [
{
"id": "baz",
"recording": {
"title": "foo",
"id": "bar",
"length": 59,
},
"position": 9,
"number": "A2",
}
return AlbumInfo(
album_id=id_,
album=album,
artist_id="some-id",
artist=artist,
albumstatus="Official",
tracks=[
TrackInfo(
track_id="bar",
title="foo",
artist_id="some-id",
artist=artist,
length=59,
index=9,
track_allt="A2",
)
],
"position": 5,
}
],
"artist-credit": [
{
"artist": {
"name": releases[id_][1],
"id": "some-id",
},
}
],
"release-group": {
"id": "another-id",
},
"status": "Official",
}
}
)
def mocked_get_recording_by_id(
id_, includes=[], release_status=[], release_type=[]
):
"""Mimic musicbrainzngs.get_recording_by_id, accepting only a restricted
list of MB ids (ID_RECORDING_0, ID_RECORDING_1). The returned dict differs
only in the recording title and artist name, so that ID_RECORDING_0 is a
closer match to the items created by ImportHelper.prepare_album_for_import().
def mocked_get_track_by_id(id_):
"""Return track candidate for the given id.
The two tracks differ only in the release title and artist name, so that
ID_RELEASE_0 is a closer match to the items created by
ImportHelper.prepare_album_for_import().
"""
# Map IDs to (recording title, artist), so the distances are different.
releases = {
ImportMusicBrainzIdTest.ID_RECORDING_0: (
"VALID_RECORDING_0",
"TAG ARTIST",
),
ImportMusicBrainzIdTest.ID_RECORDING_1: (
"VALID_RECORDING_1",
"DISTANT_MATCH",
),
}
title, artist = {
ImportIdTest.ID_RECORDING_0: ("VALID_RECORDING_0", "TAG ARTIST"),
ImportIdTest.ID_RECORDING_1: ("VALID_RECORDING_1", "DISTANT_MATCH"),
}[id_]
return {
"recording": {
"title": releases[id_][0],
"id": id_,
"length": 59,
"artist-credit": [
{
"artist": {
"name": releases[id_][1],
"id": "some-id",
},
}
],
}
}
return TrackInfo(
track_id=id_,
title=title,
artist_id="some-id",
artist=artist,
length=59,
)
@patch(
"musicbrainzngs.get_recording_by_id",
Mock(side_effect=mocked_get_recording_by_id),
)
@patch(
"musicbrainzngs.get_release_by_id",
Mock(side_effect=mocked_get_release_by_id),
)
class ImportMusicBrainzIdTest(ImportTestCase):
"""Test the --musicbrainzid argument."""
MB_RELEASE_PREFIX = "https://musicbrainz.org/release/"
MB_RECORDING_PREFIX = "https://musicbrainz.org/recording/"
@patch("beets.plugins.track_for_id", Mock(side_effect=mocked_get_track_by_id))
@patch("beets.plugins.album_for_id", Mock(side_effect=mocked_get_album_by_id))
class ImportIdTest(ImportTestCase):
ID_RELEASE_0 = "00000000-0000-0000-0000-000000000000"
ID_RELEASE_1 = "11111111-1111-1111-1111-111111111111"
ID_RECORDING_0 = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
@ -1797,21 +1742,14 @@ class ImportMusicBrainzIdTest(ImportTestCase):
self.prepare_album_for_import(1)
def test_one_mbid_one_album(self):
self.setup_importer(
search_ids=[self.MB_RELEASE_PREFIX + self.ID_RELEASE_0]
)
self.setup_importer(search_ids=[self.ID_RELEASE_0])
self.importer.add_choice(importer.action.APPLY)
self.importer.run()
assert self.lib.albums().get().album == "VALID_RELEASE_0"
def test_several_mbid_one_album(self):
self.setup_importer(
search_ids=[
self.MB_RELEASE_PREFIX + self.ID_RELEASE_0,
self.MB_RELEASE_PREFIX + self.ID_RELEASE_1,
]
)
self.setup_importer(search_ids=[self.ID_RELEASE_0, self.ID_RELEASE_1])
self.importer.add_choice(2) # Pick the 2nd best match (release 1).
self.importer.add_choice(importer.action.APPLY)
@ -1819,9 +1757,7 @@ class ImportMusicBrainzIdTest(ImportTestCase):
assert self.lib.albums().get().album == "VALID_RELEASE_1"
def test_one_mbid_one_singleton(self):
self.setup_singleton_importer(
search_ids=[self.MB_RECORDING_PREFIX + self.ID_RECORDING_0]
)
self.setup_singleton_importer(search_ids=[self.ID_RECORDING_0])
self.importer.add_choice(importer.action.APPLY)
self.importer.run()
@ -1829,10 +1765,7 @@ class ImportMusicBrainzIdTest(ImportTestCase):
def test_several_mbid_one_singleton(self):
self.setup_singleton_importer(
search_ids=[
self.MB_RECORDING_PREFIX + self.ID_RECORDING_0,
self.MB_RECORDING_PREFIX + self.ID_RECORDING_1,
]
search_ids=[self.ID_RECORDING_0, self.ID_RECORDING_1]
)
self.importer.add_choice(2) # Pick the 2nd best match (recording 1).
@ -1845,11 +1778,7 @@ class ImportMusicBrainzIdTest(ImportTestCase):
task = importer.ImportTask(
paths=self.import_dir, toppath="top path", items=[_common.item()]
)
task.search_ids = [
self.MB_RELEASE_PREFIX + self.ID_RELEASE_0,
self.MB_RELEASE_PREFIX + self.ID_RELEASE_1,
"an invalid and discarded id",
]
task.search_ids = [self.ID_RELEASE_0, self.ID_RELEASE_1]
task.lookup_candidates()
assert {"VALID_RELEASE_0", "VALID_RELEASE_1"} == {
@ -1861,11 +1790,7 @@ class ImportMusicBrainzIdTest(ImportTestCase):
task = importer.SingletonImportTask(
toppath="top path", item=_common.item()
)
task.search_ids = [
self.MB_RECORDING_PREFIX + self.ID_RECORDING_0,
self.MB_RECORDING_PREFIX + self.ID_RECORDING_1,
"an invalid and discarded id",
]
task.search_ids = [self.ID_RECORDING_0, self.ID_RECORDING_1]
task.lookup_candidates()
assert {"VALID_RECORDING_0", "VALID_RECORDING_1"} == {