diff --git a/beets/autotag/__init__.py b/beets/autotag/__init__.py index fab0fbbae..2f632f1ee 100644 --- a/beets/autotag/__init__.py +++ b/beets/autotag/__init__.py @@ -42,6 +42,8 @@ def apply_item_metadata(item, track_info): item.mb_trackid = track_info.track_id if track_info.artist_id: item.mb_artistid = track_info.artist_id + if track_info.data_source: + item.data_source = track_info.data_source # At the moment, the other metadata is left intact (including album # and track number). Perhaps these should be emptied? @@ -125,7 +127,8 @@ def apply_metadata(album_info, mapping): 'language', 'country', 'albumstatus', - 'albumdisambig'): + 'albumdisambig', + 'data_source',): value = getattr(album_info, field) if value is not None: item[field] = value diff --git a/beets/autotag/hooks.py b/beets/autotag/hooks.py index 12d11a0b3..3a4f96548 100644 --- a/beets/autotag/hooks.py +++ b/beets/autotag/hooks.py @@ -137,6 +137,8 @@ class TrackInfo(object): - ``artist_sort``: name of the track artist for sorting - ``disctitle``: name of the individual medium (subtitle) - ``artist_credit``: Recording-specific artist name + - ``data_source``: The original data source (MusicBrainz, Discogs, etc.) + - ``data_url``: The data source release URL. Only ``title`` and ``track_id`` are required. The rest of the fields may be None. The indices ``index``, ``medium``, and ``medium_index`` diff --git a/beets/autotag/mb.py b/beets/autotag/mb.py index c25599751..b9402f3dc 100644 --- a/beets/autotag/mb.py +++ b/beets/autotag/mb.py @@ -161,6 +161,7 @@ def track_info(recording, index=None, medium=None, medium_index=None, medium=medium, medium_index=medium_index, medium_total=medium_total, + data_source='MusicBrainz', data_url=track_url(recording['id']), ) diff --git a/beets/library.py b/beets/library.py index 7a6ed7ea4..8d95561f7 100644 --- a/beets/library.py +++ b/beets/library.py @@ -393,6 +393,10 @@ class Item(LibModel): _search_fields = ('artist', 'title', 'comments', 'album', 'albumartist', 'genre') + _types = { + 'data_source': types.STRING, + } + _media_fields = set(MediaFile.readable_fields()) \ .intersection(_fields.keys()) """Set of item fields that are backed by `MediaFile` fields. @@ -805,7 +809,8 @@ class Album(LibModel): _search_fields = ('album', 'albumartist', 'genre') _types = { - 'path': PathType(), + 'path': PathType(), + 'data_source': types.STRING, } _sorts = { diff --git a/docs/changelog.rst b/docs/changelog.rst index 81493428c..329770102 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -42,6 +42,8 @@ Features: * A new ``filesize`` field on items indicates the number of bytes in the file. :bug:`1291` * The number of missing/unmatched tracks is shown during import. :bug:`1088` +* The data source used during import (e.g., MusicBrainz) is now saved as a + flexible attribute `data_source` of an Item/Album. :bug:`1311` Core changes: diff --git a/test/test_autotag.py b/test/test_autotag.py index 7e018a4c1..6393a0f2f 100644 --- a/test/test_autotag.py +++ b/test/test_autotag.py @@ -789,6 +789,13 @@ class ApplyTest(_common.TestCase, ApplyTestUtil): self.assertEqual(self.items[0].month, 2) self.assertEqual(self.items[0].day, 3) + def test_data_source_applied(self): + my_info = copy.deepcopy(self.info) + my_info.data_source = 'MusicBrainz' + self._apply(info=my_info) + + self.assertEqual(self.items[0].data_source, 'MusicBrainz') + class ApplyCompilationTest(_common.TestCase, ApplyTestUtil): def setUp(self): diff --git a/test/test_importer.py b/test/test_importer.py index 45901bc6a..a9863b926 100644 --- a/test/test_importer.py +++ b/test/test_importer.py @@ -625,6 +625,15 @@ class ImportTest(_common.TestCase, ImportHelper): self.assertIn('No files imported from {0}'.format(import_dir), logs) + def test_asis_no_data_source(self): + self.assertEqual(self.lib.items().get(), None) + + self.importer.add_choice(importer.action.ASIS) + self.importer.run() + + with self.assertRaises(AttributeError): + self.lib.items().get().data_source + class ImportTracksTest(_common.TestCase, ImportHelper): """Test TRACKS and APPLY choice. diff --git a/test/test_mb.py b/test/test_mb.py index 3e5f721ff..c1c93bbdc 100644 --- a/test/test_mb.py +++ b/test/test_mb.py @@ -316,6 +316,11 @@ class MBAlbumInfoTest(_common.TestCase): self.assertEqual(track.artist_sort, 'TRACK ARTIST SORT NAME') self.assertEqual(track.artist_credit, 'TRACK ARTIST CREDIT') + def test_data_source(self): + release = self._make_release() + d = mb.album_info(release) + self.assertEqual(d.data_source, 'MusicBrainz') + class ParseIDTest(_common.TestCase): def test_parse_id_correct(self):