From 0980c82959cf806bae5824450635a11a1cdd9925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0ar=C5=ABnas=20Nejus?= Date: Mon, 17 Feb 2025 23:29:36 +0000 Subject: [PATCH] musicbrainz: update patches --- beets/test/helper.py | 43 ++++----- beets/ui/commands.py | 2 +- test/test_importer.py | 215 ++++++++++++++---------------------------- 3 files changed, 88 insertions(+), 172 deletions(-) diff --git a/beets/test/helper.py b/beets/test/helper.py index ca9b8f406..f83f274d5 100644 --- a/beets/test/helper.py +++ b/beets/test/helper.py @@ -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, diff --git a/beets/ui/commands.py b/beets/ui/commands.py index 12ea4c94d..94693ea4e 100755 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -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}" diff --git a/test/test_importer.py b/test/test_importer.py index 804266116..dad30749b 100644 --- a/test/test_importer.py +++ b/test/test_importer.py @@ -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( - artist="artist", - title="title", - track_id="new trackid", - index=0, - ) - ] +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", - } - ], - "position": 5, - } - ], - "artist-credit": [ - { - "artist": { - "name": releases[id_][1], - "id": "some-id", - }, - } - ], - "release-group": { - "id": "another-id", - }, - "status": "Official", - } - } + 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", + ) + ], + ) -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"} == {