diff --git a/beets/autotag/hooks.py b/beets/autotag/hooks.py index 63ee522676..e0e2a5a795 100644 --- a/beets/autotag/hooks.py +++ b/beets/autotag/hooks.py @@ -97,15 +97,15 @@ def __init__( self.artist = artist self.artist_credit = artist_credit self.artist_id = artist_id - self.artists = artists or [] - self.artists_credit = artists_credit or [] - self.artists_ids = artists_ids or [] + self.artists = artists + self.artists_credit = artists_credit + self.artists_ids = artists_ids self.artist_sort = artist_sort - self.artists_sort = artists_sort or [] + self.artists_sort = artists_sort self.data_source = data_source self.data_url = data_url self.genre = None - self.genres = genres or [] + self.genres = genres self.media = media self.update(kwargs) @@ -160,7 +160,7 @@ def __init__( self.albumdisambig = albumdisambig self.albumstatus = albumstatus self.albumtype = albumtype - self.albumtypes = albumtypes or [] + self.albumtypes = albumtypes self.asin = asin self.barcode = barcode self.catalognum = catalognum diff --git a/docs/changelog.rst b/docs/changelog.rst index 711749a9f7..e759c9df0c 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -44,6 +44,9 @@ Bug fixes - :doc:`plugins/zero`: When the ``omit_single_disc`` option is set, ``disctotal`` is zeroed alongside ``disc``. - :doc:`plugins/fetchart`: Prevent deletion of configured fallback cover art +- In autotagging, initialise empty multi-valued fields with ``None`` instead of + empty list, which caused beets to overwrite existing metadata with empty list + values instead of leaving them unchanged. :bug:`6403` For plugin developers ~~~~~~~~~~~~~~~~~~~~~ diff --git a/test/autotag/test_autotag.py b/test/autotag/test_autotag.py new file mode 100644 index 0000000000..903f9095c0 --- /dev/null +++ b/test/autotag/test_autotag.py @@ -0,0 +1,317 @@ +# This file is part of beets. +# Copyright 2016, Adrian Sampson. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. + +"""Tests for autotagging functionality.""" + +import operator + +import pytest + +from beets import autotag +from beets.autotag import AlbumInfo, TrackInfo, correct_list_fields, match +from beets.library import Item +from beets.test.helper import BeetsTestCase + + +class TestAssignment: + A = "one" + B = "two" + C = "three" + + @pytest.fixture(autouse=True) + def config(self, config): + config["match"]["track_length_grace"] = 10 + config["match"]["track_length_max"] = 30 + + @pytest.mark.parametrize( + # 'expected' is a tuple of expected (mapping, extra_items, extra_tracks) + "item_titles, track_titles, expected", + [ + # items ordering gets corrected + ([A, C, B], [A, B, C], ({A: A, B: B, C: C}, [], [])), + # unmatched tracks are returned as 'extra_tracks' + # the first track is unmatched + ([B, C], [A, B, C], ({B: B, C: C}, [], [A])), + # the middle track is unmatched + ([A, C], [A, B, C], ({A: A, C: C}, [], [B])), + # the last track is unmatched + ([A, B], [A, B, C], ({A: A, B: B}, [], [C])), + # unmatched items are returned as 'extra_items' + ([A, C, B], [A, C], ({A: A, C: C}, [B], [])), + ], + ) + def test_assign_tracks(self, item_titles, track_titles, expected): + expected_mapping, expected_extra_items, expected_extra_tracks = expected + + items = [Item(title=title) for title in item_titles] + tracks = [TrackInfo(title=title) for title in track_titles] + + item_info_pairs, extra_items, extra_tracks = match.assign_items( + items, tracks + ) + + assert ( + {i.title: t.title for i, t in item_info_pairs}, + [i.title for i in extra_items], + [t.title for t in extra_tracks], + ) == (expected_mapping, expected_extra_items, expected_extra_tracks) + + def test_order_works_when_track_names_are_entirely_wrong(self): + # A real-world test case contributed by a user. + def item(i, length): + return Item( + artist="ben harper", + album="burn to shine", + title=f"ben harper - Burn to Shine {i}", + track=i, + length=length, + ) + + items = [] + items.append(item(1, 241.37243007106997)) + items.append(item(2, 342.27781704375036)) + items.append(item(3, 245.95070222338137)) + items.append(item(4, 472.87662515485437)) + items.append(item(5, 279.1759535763187)) + items.append(item(6, 270.33333768012)) + items.append(item(7, 247.83435613222923)) + items.append(item(8, 216.54504531525072)) + items.append(item(9, 225.72775379800484)) + items.append(item(10, 317.7643606963552)) + items.append(item(11, 243.57001238834192)) + items.append(item(12, 186.45916150485752)) + + def info(index, title, length): + return TrackInfo(title=title, length=length, index=index) + + trackinfo = [] + trackinfo.append(info(1, "Alone", 238.893)) + trackinfo.append(info(2, "The Woman in You", 341.44)) + trackinfo.append(info(3, "Less", 245.59999999999999)) + trackinfo.append(info(4, "Two Hands of a Prayer", 470.49299999999999)) + trackinfo.append(info(5, "Please Bleed", 277.86599999999999)) + trackinfo.append(info(6, "Suzie Blue", 269.30599999999998)) + trackinfo.append(info(7, "Steal My Kisses", 245.36000000000001)) + trackinfo.append(info(8, "Burn to Shine", 214.90600000000001)) + trackinfo.append(info(9, "Show Me a Little Shame", 224.0929999999999)) + trackinfo.append(info(10, "Forgiven", 317.19999999999999)) + trackinfo.append(info(11, "Beloved One", 243.733)) + trackinfo.append(info(12, "In the Lord's Arms", 186.13300000000001)) + + expected = list(zip(items, trackinfo)), [], [] + + assert match.assign_items(items, trackinfo) == expected + + +class ApplyTest(BeetsTestCase): + def _apply(self, per_disc_numbering=False, artist_credit=False): + info = self.info + item_info_pairs = list(zip(self.items, info.tracks)) + self.config["per_disc_numbering"] = per_disc_numbering + self.config["artist_credit"] = artist_credit + autotag.apply_metadata(self.info, item_info_pairs) + + def setUp(self): + super().setUp() + + self.items = [Item(), Item()] + self.info = AlbumInfo( + tracks=[ + TrackInfo( + title="title", + track_id="dfa939ec-118c-4d0f-84a0-60f3d1e6522c", + medium=1, + medium_index=1, + medium_total=1, + index=1, + artist="trackArtist", + artist_credit="trackArtistCredit", + artists_credit=["trackArtistCredit"], + artist_sort="trackArtistSort", + artists_sort=["trackArtistSort"], + ), + TrackInfo( + title="title2", + track_id="40130ed1-a27c-42fd-a328-1ebefb6caef4", + medium=2, + medium_index=1, + index=2, + medium_total=1, + ), + ], + artist="albumArtist", + artists=["albumArtist", "albumArtist2"], + album="album", + album_id="7edb51cb-77d6-4416-a23c-3a8c2994a2c7", + artist_id="a6623d39-2d8e-4f70-8242-0a9553b91e50", + artists_ids=None, + artist_credit="albumArtistCredit", + artists_credit=["albumArtistCredit1", "albumArtistCredit2"], + artist_sort=None, + artists_sort=["albumArtistSort", "albumArtistSort2"], + albumtype="album", + va=True, + mediums=2, + data_source="MusicBrainz", + year=2013, + month=12, + day=18, + genres=["Rock", "Pop"], + ) + + common_expected = { + "album": "album", + "albumartist_credit": "albumArtistCredit", + "albumartist_sort": "", + "albumartist": "albumArtist", + "albumartists": ["albumArtist", "albumArtist2"], + "albumartists_credit": [ + "albumArtistCredit1", + "albumArtistCredit2", + ], + "albumartists_sort": ["albumArtistSort", "albumArtistSort2"], + "albumtype": "album", + "albumtypes": ["album"], + "comp": True, + "disctotal": 2, + "mb_albumartistid": "a6623d39-2d8e-4f70-8242-0a9553b91e50", + "mb_albumartistids": ["a6623d39-2d8e-4f70-8242-0a9553b91e50"], + "mb_albumid": "7edb51cb-77d6-4416-a23c-3a8c2994a2c7", + "mb_artistid": "a6623d39-2d8e-4f70-8242-0a9553b91e50", + "mb_artistids": ["a6623d39-2d8e-4f70-8242-0a9553b91e50"], + "tracktotal": 2, + "year": 2013, + "month": 12, + "day": 18, + "genres": ["Rock", "Pop"], + } + + self.expected_tracks = [ + { + **common_expected, + "artist": "trackArtist", + "artists": ["albumArtist", "albumArtist2"], + "artist_credit": "trackArtistCredit", + "artist_sort": "trackArtistSort", + "artists_credit": ["trackArtistCredit"], + "artists_sort": ["trackArtistSort"], + "disc": 1, + "mb_trackid": "dfa939ec-118c-4d0f-84a0-60f3d1e6522c", + "title": "title", + "track": 1, + }, + { + **common_expected, + "artist": "albumArtist", + "artists": ["albumArtist", "albumArtist2"], + "artist_credit": "albumArtistCredit", + "artist_sort": "", + "artists_credit": [ + "albumArtistCredit1", + "albumArtistCredit2", + ], + "artists_sort": ["albumArtistSort", "albumArtistSort2"], + "disc": 2, + "mb_trackid": "40130ed1-a27c-42fd-a328-1ebefb6caef4", + "title": "title2", + "track": 2, + }, + ] + + def test_autotag_items(self): + self._apply() + + keys = self.expected_tracks[0].keys() + get_values = operator.itemgetter(*keys) + + applied_data = [ + dict(zip(keys, get_values(dict(i)))) for i in self.items + ] + + assert applied_data == self.expected_tracks + + def test_per_disc_numbering(self): + self._apply(per_disc_numbering=True) + + assert self.items[0].track == 1 + assert self.items[1].track == 1 + assert self.items[0].tracktotal == 1 + assert self.items[1].tracktotal == 1 + + def test_artist_credit_prefers_artist_over_albumartist_credit(self): + self.info.tracks[0].update(artist="oldArtist", artist_credit=None) + + self._apply(artist_credit=True) + + assert self.items[0].artist == "oldArtist" + + def test_artist_credit_falls_back_to_albumartist(self): + self.info.artist_credit = None + + self._apply(artist_credit=True) + + assert self.items[1].artist == "albumArtist" + + def test_date_only_zeroes_month_and_day(self): + self.items = [Item(year=1, month=2, day=3)] + self.info.update(year=2013, month=None, day=None) + + self._apply() + + assert self.items[0].year == 2013 + assert self.items[0].month == 0 + assert self.items[0].day == 0 + + def test_missing_date_applies_nothing(self): + self.items = [Item(year=1, month=2, day=3)] + self.info.update(year=None, month=None, day=None) + + self._apply() + + assert self.items[0].year == 1 + assert self.items[0].month == 2 + assert self.items[0].day == 3 + + +@pytest.mark.parametrize( + "single_field,list_field", + [ + ("mb_artistid", "mb_artistids"), + ("mb_albumartistid", "mb_albumartistids"), + ("albumtype", "albumtypes"), + ], +) +@pytest.mark.parametrize( + "single_value,list_value", + [ + (None, []), + (None, ["1"]), + (None, ["1", "2"]), + ("1", []), + ("1", ["1"]), + ("1", ["1", "2"]), + ("1", ["2", "1"]), + ], +) +def test_correct_list_fields( + single_field, list_field, single_value, list_value +): + """Ensure that the first value in a list field matches the single field.""" + data = {single_field: single_value, list_field: list_value} + item = Item(**data) + + correct_list_fields(item) + + single_val, list_val = item[single_field], item[list_field] + assert (not single_val and not list_val) or single_val == list_val[0] diff --git a/test/plugins/test_musicbrainz.py b/test/plugins/test_musicbrainz.py index e000e16ec8..dad31bc3c3 100644 --- a/test/plugins/test_musicbrainz.py +++ b/test/plugins/test_musicbrainz.py @@ -539,7 +539,7 @@ def test_no_genres(self): config["musicbrainz"]["genres"] = False release = self._make_release() d = self.mb.album_info(release) - assert d.genres == [] + assert d.genres is None def test_ignored_media(self): config["match"]["ignored_media"] = ["IGNORED1", "IGNORED2"] diff --git a/test/test_autotag.py b/test/test_autotag.py deleted file mode 100644 index 119ca15e83..0000000000 --- a/test/test_autotag.py +++ /dev/null @@ -1,477 +0,0 @@ -# This file is part of beets. -# Copyright 2016, Adrian Sampson. -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. - -"""Tests for autotagging functionality.""" - -import pytest - -from beets import autotag, config -from beets.autotag import AlbumInfo, TrackInfo, correct_list_fields, match -from beets.library import Item -from beets.test.helper import BeetsTestCase - - -class TestAssignment: - A = "one" - B = "two" - C = "three" - - @pytest.fixture(autouse=True) - def config(self, config): - config["match"]["track_length_grace"] = 10 - config["match"]["track_length_max"] = 30 - - @pytest.mark.parametrize( - # 'expected' is a tuple of expected (mapping, extra_items, extra_tracks) - "item_titles, track_titles, expected", - [ - # items ordering gets corrected - ([A, C, B], [A, B, C], ({A: A, B: B, C: C}, [], [])), - # unmatched tracks are returned as 'extra_tracks' - # the first track is unmatched - ([B, C], [A, B, C], ({B: B, C: C}, [], [A])), - # the middle track is unmatched - ([A, C], [A, B, C], ({A: A, C: C}, [], [B])), - # the last track is unmatched - ([A, B], [A, B, C], ({A: A, B: B}, [], [C])), - # unmatched items are returned as 'extra_items' - ([A, C, B], [A, C], ({A: A, C: C}, [B], [])), - ], - ) - def test_assign_tracks(self, item_titles, track_titles, expected): - expected_mapping, expected_extra_items, expected_extra_tracks = expected - - items = [Item(title=title) for title in item_titles] - tracks = [TrackInfo(title=title) for title in track_titles] - - item_info_pairs, extra_items, extra_tracks = match.assign_items( - items, tracks - ) - - assert ( - {i.title: t.title for i, t in item_info_pairs}, - [i.title for i in extra_items], - [t.title for t in extra_tracks], - ) == (expected_mapping, expected_extra_items, expected_extra_tracks) - - def test_order_works_when_track_names_are_entirely_wrong(self): - # A real-world test case contributed by a user. - def item(i, length): - return Item( - artist="ben harper", - album="burn to shine", - title=f"ben harper - Burn to Shine {i}", - track=i, - length=length, - ) - - items = [] - items.append(item(1, 241.37243007106997)) - items.append(item(2, 342.27781704375036)) - items.append(item(3, 245.95070222338137)) - items.append(item(4, 472.87662515485437)) - items.append(item(5, 279.1759535763187)) - items.append(item(6, 270.33333768012)) - items.append(item(7, 247.83435613222923)) - items.append(item(8, 216.54504531525072)) - items.append(item(9, 225.72775379800484)) - items.append(item(10, 317.7643606963552)) - items.append(item(11, 243.57001238834192)) - items.append(item(12, 186.45916150485752)) - - def info(index, title, length): - return TrackInfo(title=title, length=length, index=index) - - trackinfo = [] - trackinfo.append(info(1, "Alone", 238.893)) - trackinfo.append(info(2, "The Woman in You", 341.44)) - trackinfo.append(info(3, "Less", 245.59999999999999)) - trackinfo.append(info(4, "Two Hands of a Prayer", 470.49299999999999)) - trackinfo.append(info(5, "Please Bleed", 277.86599999999999)) - trackinfo.append(info(6, "Suzie Blue", 269.30599999999998)) - trackinfo.append(info(7, "Steal My Kisses", 245.36000000000001)) - trackinfo.append(info(8, "Burn to Shine", 214.90600000000001)) - trackinfo.append(info(9, "Show Me a Little Shame", 224.0929999999999)) - trackinfo.append(info(10, "Forgiven", 317.19999999999999)) - trackinfo.append(info(11, "Beloved One", 243.733)) - trackinfo.append(info(12, "In the Lord's Arms", 186.13300000000001)) - - expected = list(zip(items, trackinfo)), [], [] - - assert match.assign_items(items, trackinfo) == expected - - -class ApplyTestUtil: - def _apply(self, info=None, per_disc_numbering=False, artist_credit=False): - info = info or self.info - item_info_pairs = list(zip(self.items, info.tracks)) - config["per_disc_numbering"] = per_disc_numbering - config["artist_credit"] = artist_credit - autotag.apply_metadata(info, item_info_pairs) - - -class ApplyTest(BeetsTestCase, ApplyTestUtil): - def setUp(self): - super().setUp() - - self.items = [] - self.items.append(Item({})) - self.items.append(Item({})) - trackinfo = [] - trackinfo.append( - TrackInfo( - title="oneNew", - track_id="dfa939ec-118c-4d0f-84a0-60f3d1e6522c", - medium=1, - medium_index=1, - medium_total=1, - index=1, - artist_credit="trackArtistCredit", - artists_credit=["trackArtistCredit"], - artist_sort="trackArtistSort", - artists_sort=["trackArtistSort"], - ) - ) - trackinfo.append( - TrackInfo( - title="twoNew", - track_id="40130ed1-a27c-42fd-a328-1ebefb6caef4", - medium=2, - medium_index=1, - index=2, - medium_total=1, - ) - ) - self.info = AlbumInfo( - tracks=trackinfo, - artist="artistNew", - artists=["artistNew", "artistNew2"], - album="albumNew", - album_id="7edb51cb-77d6-4416-a23c-3a8c2994a2c7", - artist_id="a6623d39-2d8e-4f70-8242-0a9553b91e50", - artists_ids=[ - "a6623d39-2d8e-4f70-8242-0a9553b91e50", - "a6623d39-2d8e-4f70-8242-0a9553b91e51", - ], - artist_credit="albumArtistCredit", - artists_credit=["albumArtistCredit", "albumArtistCredit2"], - artist_sort="albumArtistSort", - artists_sort=["albumArtistSort", "albumArtistSort2"], - albumtype="album", - va=False, - mediums=2, - ) - - def test_titles_applied(self): - self._apply() - assert self.items[0].title == "oneNew" - assert self.items[1].title == "twoNew" - - def test_album_and_artist_applied_to_all(self): - self._apply() - assert self.items[0].album == "albumNew" - assert self.items[1].album == "albumNew" - assert self.items[0].artist == "artistNew" - assert self.items[1].artist == "artistNew" - assert self.items[0].artists == ["artistNew", "artistNew2"] - assert self.items[1].artists == ["artistNew", "artistNew2"] - assert self.items[0].albumartists == ["artistNew", "artistNew2"] - assert self.items[1].albumartists == ["artistNew", "artistNew2"] - - def test_track_index_applied(self): - self._apply() - assert self.items[0].track == 1 - assert self.items[1].track == 2 - - def test_track_total_applied(self): - self._apply() - assert self.items[0].tracktotal == 2 - assert self.items[1].tracktotal == 2 - - def test_disc_index_applied(self): - self._apply() - assert self.items[0].disc == 1 - assert self.items[1].disc == 2 - - def test_disc_total_applied(self): - self._apply() - assert self.items[0].disctotal == 2 - assert self.items[1].disctotal == 2 - - def test_per_disc_numbering(self): - self._apply(per_disc_numbering=True) - assert self.items[0].track == 1 - assert self.items[1].track == 1 - - def test_per_disc_numbering_track_total(self): - self._apply(per_disc_numbering=True) - assert self.items[0].tracktotal == 1 - assert self.items[1].tracktotal == 1 - - def test_artist_credit(self): - self._apply(artist_credit=True) - assert self.items[0].artist == "trackArtistCredit" - assert self.items[1].artist == "albumArtistCredit" - assert self.items[0].albumartist == "albumArtistCredit" - assert self.items[1].albumartist == "albumArtistCredit" - assert self.items[0].albumartists == [ - "albumArtistCredit", - "albumArtistCredit2", - ] - assert self.items[1].albumartists == [ - "albumArtistCredit", - "albumArtistCredit2", - ] - - def test_artist_credit_prefers_artist_over_albumartist_credit(self): - self.info.tracks[0].artist = "oldArtist" - self.info.tracks[0].artist_credit = None - self._apply(artist_credit=True) - assert self.items[0].artist == "oldArtist" - - def test_artist_credit_falls_back_to_albumartist(self): - self.info.artist_credit = None - self._apply(artist_credit=True) - assert self.items[1].artist == "artistNew" - - def test_mb_trackid_applied(self): - self._apply() - assert ( - self.items[0].mb_trackid == "dfa939ec-118c-4d0f-84a0-60f3d1e6522c" - ) - assert ( - self.items[1].mb_trackid == "40130ed1-a27c-42fd-a328-1ebefb6caef4" - ) - - def test_mb_albumid_and_artistid_applied(self): - self._apply() - for item in self.items: - assert item.mb_albumid == "7edb51cb-77d6-4416-a23c-3a8c2994a2c7" - assert item.mb_artistid == "a6623d39-2d8e-4f70-8242-0a9553b91e50" - assert item.mb_artistids == [ - "a6623d39-2d8e-4f70-8242-0a9553b91e50", - "a6623d39-2d8e-4f70-8242-0a9553b91e51", - ] - - def test_albumtype_applied(self): - self._apply() - assert self.items[0].albumtype == "album" - assert self.items[1].albumtype == "album" - - def test_album_artist_overrides_empty_track_artist(self): - my_info = self.info.copy() - self._apply(info=my_info) - assert self.items[0].artist == "artistNew" - assert self.items[1].artist == "artistNew" - assert self.items[0].artists == ["artistNew", "artistNew2"] - assert self.items[1].artists == ["artistNew", "artistNew2"] - - def test_album_artist_overridden_by_nonempty_track_artist(self): - my_info = self.info.copy() - my_info.tracks[0].artist = "artist1!" - my_info.tracks[1].artist = "artist2!" - my_info.tracks[0].artists = ["artist1!", "artist1!!"] - my_info.tracks[1].artists = ["artist2!", "artist2!!"] - self._apply(info=my_info) - assert self.items[0].artist == "artist1!" - assert self.items[1].artist == "artist2!" - assert self.items[0].artists == ["artist1!", "artist1!!"] - assert self.items[1].artists == ["artist2!", "artist2!!"] - - def test_artist_credit_applied(self): - self._apply() - assert self.items[0].albumartist_credit == "albumArtistCredit" - assert self.items[0].albumartists_credit == [ - "albumArtistCredit", - "albumArtistCredit2", - ] - assert self.items[0].artist_credit == "trackArtistCredit" - assert self.items[0].artists_credit == ["trackArtistCredit"] - assert self.items[1].albumartist_credit == "albumArtistCredit" - assert self.items[1].albumartists_credit == [ - "albumArtistCredit", - "albumArtistCredit2", - ] - assert self.items[1].artist_credit == "albumArtistCredit" - assert self.items[1].artists_credit == [ - "albumArtistCredit", - "albumArtistCredit2", - ] - - def test_artist_sort_applied(self): - self._apply() - assert self.items[0].albumartist_sort == "albumArtistSort" - assert self.items[0].albumartists_sort == [ - "albumArtistSort", - "albumArtistSort2", - ] - assert self.items[0].artist_sort == "trackArtistSort" - assert self.items[0].artists_sort == ["trackArtistSort"] - assert self.items[1].albumartist_sort == "albumArtistSort" - assert self.items[1].albumartists_sort == [ - "albumArtistSort", - "albumArtistSort2", - ] - assert self.items[1].artist_sort == "albumArtistSort" - assert self.items[1].artists_sort == [ - "albumArtistSort", - "albumArtistSort2", - ] - - def test_full_date_applied(self): - my_info = self.info.copy() - my_info.year = 2013 - my_info.month = 12 - my_info.day = 18 - self._apply(info=my_info) - - assert self.items[0].year == 2013 - assert self.items[0].month == 12 - assert self.items[0].day == 18 - - def test_date_only_zeros_month_and_day(self): - self.items = [] - self.items.append(Item(year=1, month=2, day=3)) - self.items.append(Item(year=4, month=5, day=6)) - - my_info = self.info.copy() - my_info.year = 2013 - self._apply(info=my_info) - - assert self.items[0].year == 2013 - assert self.items[0].month == 0 - assert self.items[0].day == 0 - - def test_missing_date_applies_nothing(self): - self.items = [] - self.items.append(Item(year=1, month=2, day=3)) - self.items.append(Item(year=4, month=5, day=6)) - - self._apply() - - assert self.items[0].year == 1 - assert self.items[0].month == 2 - assert self.items[0].day == 3 - - def test_data_source_applied(self): - my_info = self.info.copy() - my_info.data_source = "MusicBrainz" - self._apply(info=my_info) - - assert self.items[0].data_source == "MusicBrainz" - - -class ApplyCompilationTest(BeetsTestCase, ApplyTestUtil): - def setUp(self): - super().setUp() - - self.items = [] - self.items.append(Item({})) - self.items.append(Item({})) - trackinfo = [] - trackinfo.append( - TrackInfo( - title="oneNew", - track_id="dfa939ec-118c-4d0f-84a0-60f3d1e6522c", - artist="artistOneNew", - artist_id="a05686fc-9db2-4c23-b99e-77f5db3e5282", - index=1, - ) - ) - trackinfo.append( - TrackInfo( - title="twoNew", - track_id="40130ed1-a27c-42fd-a328-1ebefb6caef4", - artist="artistTwoNew", - artist_id="80b3cf5e-18fe-4c59-98c7-e5bb87210710", - index=2, - ) - ) - self.info = AlbumInfo( - tracks=trackinfo, - artist="variousNew", - album="albumNew", - album_id="3b69ea40-39b8-487f-8818-04b6eff8c21a", - artist_id="89ad4ac3-39f7-470e-963a-56509c546377", - albumtype="compilation", - ) - - def test_album_and_track_artists_separate(self): - self._apply() - assert self.items[0].artist == "artistOneNew" - assert self.items[1].artist == "artistTwoNew" - assert self.items[0].albumartist == "variousNew" - assert self.items[1].albumartist == "variousNew" - - def test_mb_albumartistid_applied(self): - self._apply() - assert ( - self.items[0].mb_albumartistid - == "89ad4ac3-39f7-470e-963a-56509c546377" - ) - assert ( - self.items[1].mb_albumartistid - == "89ad4ac3-39f7-470e-963a-56509c546377" - ) - assert ( - self.items[0].mb_artistid == "a05686fc-9db2-4c23-b99e-77f5db3e5282" - ) - assert ( - self.items[1].mb_artistid == "80b3cf5e-18fe-4c59-98c7-e5bb87210710" - ) - - def test_va_flag_cleared_does_not_set_comp(self): - self._apply() - assert not self.items[0].comp - assert not self.items[1].comp - - def test_va_flag_sets_comp(self): - va_info = self.info.copy() - va_info.va = True - self._apply(info=va_info) - assert self.items[0].comp - assert self.items[1].comp - - -@pytest.mark.parametrize( - "single_field,list_field", - [ - ("mb_artistid", "mb_artistids"), - ("mb_albumartistid", "mb_albumartistids"), - ("albumtype", "albumtypes"), - ], -) -@pytest.mark.parametrize( - "single_value,list_value", - [ - (None, []), - (None, ["1"]), - (None, ["1", "2"]), - ("1", []), - ("1", ["1"]), - ("1", ["1", "2"]), - ("1", ["2", "1"]), - ], -) -def test_correct_list_fields( - single_field, list_field, single_value, list_value -): - """Ensure that the first value in a list field matches the single field.""" - data = {single_field: single_value, list_field: list_value} - item = Item(**data) - - correct_list_fields(item) - - single_val, list_val = item[single_field], item[list_field] - assert (not single_val and not list_val) or single_val == list_val[0]