diff --git a/beets/importer.py b/beets/importer.py index 9a06a5a13..42ac05e6c 100644 --- a/beets/importer.py +++ b/beets/importer.py @@ -122,36 +122,44 @@ def _item_duplicate_check(lib, artist, title, recent=None): return True -def _infer_album_fields(album, task): +def _infer_album_fields(task): """Given an album and an associated import task, massage the album-level metadata. This ensures that the album artist is set and that the "compilation" flag is set automatically. """ assert task.is_album + assert task.items + + changes = {} if task.choice_flag == action.ASIS: # Taking metadata "as-is". Guess whether this album is VA. plur_artist, freq = plurality([i.artist for i in task.items]) if freq > 1 and float(freq) / len(task.items) >= SINGLE_ARTIST_THRESH: # Single-artist album. - album.albumartist = plur_artist - album.comp = False + changes['albumartist'] = plur_artist + changes['comp'] = False else: # VA. - album.albumartist = VARIOUS_ARTISTS - album.comp = True + changes['albumartist'] = VARIOUS_ARTISTS + changes['comp'] = True elif task.choice_flag == action.APPLY: # Applying autotagged metadata. Just get AA from the first # item. - if not album.albumartist: - album.albumartist = task.items[0].artist - if not album.mb_albumartistid: - album.mb_albumartistid = task.items[0].mb_artistid + if not task.items[0].albumartist: + changes['albumartist'] = task.items[0].artist + if not task.items[0].mb_albumartistid: + changes['mb_albumartistid'] = task.items[0].mb_artistid else: assert False + # Apply new metadata. + for item in task.items: + for k, v in changes.iteritems(): + setattr(item, k, v) + # Utilities for reading and writing the beets progress file, which # allows long tagging tasks to be resumed when they pause (or crash). @@ -489,6 +497,10 @@ def apply_choices(config): else: autotag.apply_item_metadata(task.item, task.info) + # Infer album-level fields. + if task.is_album: + _infer_album_fields(task) + # Move/copy files. items = task.items if task.is_album else [task.item] if config.copy and config.delete: @@ -506,7 +518,6 @@ def apply_choices(config): if task.is_album: # Add an album. album = lib.add_album(task.items) - _infer_album_fields(album, task) task.album_id = album.id else: # Add tracks. diff --git a/test/test_importer.py b/test/test_importer.py index 6071603c9..ae829acf9 100644 --- a/test/test_importer.py +++ b/test/test_importer.py @@ -285,8 +285,6 @@ class AsIsApplyTest(unittest.TestCase): class InferAlbumDataTest(unittest.TestCase): def setUp(self): - self.lib = library.Library(':memory:') - i1 = _common.item() i2 = _common.item() i3 = _common.item() @@ -298,56 +296,68 @@ class InferAlbumDataTest(unittest.TestCase): i1.mb_albumartistid = i2.mb_albumartistid = i3.mb_albumartistid = '' self.items = [i1, i2, i3] - self.album = self.lib.add_album(self.items) self.task = importer.ImportTask(path='a path', toppath='top path', items=self.items) self.task.set_null_match() + def _infer(self): + importer._infer_album_fields(self.task) + def test_asis_homogenous_single_artist(self): self.task.set_choice(importer.action.ASIS) - importer._infer_album_fields(self.album, self.task) - self.assertFalse(self.album.comp) - self.assertEqual(self.album.albumartist, self.items[2].artist) + self._infer() + self.assertFalse(self.items[0].comp) + self.assertEqual(self.items[0].albumartist, self.items[2].artist) def test_asis_heterogenous_va(self): self.items[0].artist = 'another artist' self.items[1].artist = 'some other artist' - self.lib.save() self.task.set_choice(importer.action.ASIS) - importer._infer_album_fields(self.album, self.task) + self._infer() - self.assertTrue(self.album.comp) - self.assertEqual(self.album.albumartist, 'Various Artists') + self.assertTrue(self.items[0].comp) + self.assertEqual(self.items[0].albumartist, 'Various Artists') + + def test_asis_comp_applied_to_all_items(self): + self.items[0].artist = 'another artist' + self.items[1].artist = 'some other artist' + self.task.set_choice(importer.action.ASIS) + + self._infer() + + for item in self.items: + self.assertTrue(item.comp) + self.assertEqual(item.albumartist, 'Various Artists') def test_asis_majority_artist_single_artist(self): self.items[0].artist = 'another artist' - self.lib.save() self.task.set_choice(importer.action.ASIS) - importer._infer_album_fields(self.album, self.task) + self._infer() - self.assertFalse(self.album.comp) - self.assertEqual(self.album.albumartist, self.items[2].artist) + self.assertFalse(self.items[0].comp) + self.assertEqual(self.items[0].albumartist, self.items[2].artist) def test_apply_gets_artist_and_id(self): self.task.set_choice(({}, self.items)) # APPLY - importer._infer_album_fields(self.album, self.task) + self._infer() - self.assertEqual(self.album.albumartist, self.items[0].artist) - self.assertEqual(self.album.mb_albumartistid, self.items[0].mb_artistid) + self.assertEqual(self.items[0].albumartist, self.items[0].artist) + self.assertEqual(self.items[0].mb_albumartistid, self.items[0].mb_artistid) def test_apply_lets_album_values_override(self): - self.album.albumartist = 'some album artist' - self.album.mb_albumartistid = 'some album artist id' + for item in self.items: + item.albumartist = 'some album artist' + item.mb_albumartistid = 'some album artist id' self.task.set_choice(({}, self.items)) # APPLY - importer._infer_album_fields(self.album, self.task) + self._infer() - self.assertEqual(self.album.albumartist, + self.assertEqual(self.items[0].albumartist, 'some album artist') - self.assertEqual(self.album.mb_albumartistid, + self.assertEqual(self.items[0].mb_albumartistid, 'some album artist id')