original_{year,month,day,date} fields (GC-441)

This commit is contained in:
Adrian Sampson 2013-02-08 13:28:51 -08:00
parent 15a652ab73
commit e0bb3b5cd0
10 changed files with 104 additions and 51 deletions

View file

@ -178,12 +178,11 @@ def apply_metadata(album_info, mapping):
item.albumartist_credit = album_info.artist_credit
# Release date.
if album_info.year:
item.year = album_info.year
if album_info.month:
item.month = album_info.month
if album_info.day:
item.day = album_info.day
for key in ('year', 'month', 'day',
'original_year', 'original_month', 'original_day'):
value = getattr(album_info, key)
if value:
setattr(item, key, value)
# Title.
item.title = track_info.title

View file

@ -60,7 +60,8 @@ class AlbumInfo(object):
label=None, mediums=None, artist_sort=None,
releasegroup_id=None, catalognum=None, script=None,
language=None, country=None, albumstatus=None, media=None,
albumdisambig=None, artist_credit=None):
albumdisambig=None, artist_credit=None, original_year=None,
original_month=None, original_day=None):
self.album = album
self.album_id = album_id
self.artist = artist
@ -84,6 +85,9 @@ class AlbumInfo(object):
self.media = media
self.albumdisambig = albumdisambig
self.artist_credit = artist_credit
self.original_year = original_year
self.original_month = original_month
self.original_day = original_day
# Work around a bug in python-musicbrainz-ngs that causes some
# strings to be bytes rather than Unicode.

View file

@ -135,9 +135,10 @@ def track_info(recording, index=None, medium=None, medium_index=None):
info.decode()
return info
def _set_date_str(info, date_str):
def _set_date_str(info, date_str, original=False):
"""Given a (possibly partial) YYYY-MM-DD string and an AlbumInfo
object, set the object's release date fields appropriately.
object, set the object's release date fields appropriately. If
`original`, then set the original_year, etc., fields.
"""
if date_str:
date_parts = date_str.split('-')
@ -148,6 +149,9 @@ def _set_date_str(info, date_str):
date_num = int(date_part)
except ValueError:
continue
if original:
key = 'original_' + key
setattr(info, key, date_num)
def album_info(release):
@ -205,13 +209,14 @@ def album_info(release):
if reltype:
info.albumtype = reltype.lower()
# Release date.
if 'first-release-date' in release['release-group']:
# Try earliest release date for the entire group first.
_set_date_str(info, release['release-group']['first-release-date'])
elif 'date' in release:
# Fall back to release-specific date.
_set_date_str(info, release['date'])
# Release dates.
release_date = release.get('date')
release_group_date = release['release-group'].get('first-release-date')
if not release_date:
# Fall back if release-specific date is not available.
release_date = release_group_date
_set_date_str(info, release_date, False)
_set_date_str(info, release_group_date, True)
# Label name.
if release.get('label-info-list'):

View file

@ -94,6 +94,9 @@ ITEM_FIELDS = [
('rg_track_peak', 'real', True, True),
('rg_album_gain', 'real', True, True),
('rg_album_peak', 'real', True, True),
('original_year', 'int', True, True),
('original_month', 'int', True, True),
('original_day', 'int', True, True),
('length', 'real', False, True),
('bitrate', 'int', False, True),
@ -140,6 +143,9 @@ ALBUM_FIELDS = [
('albumdisambig', 'text', True),
('rg_album_gain', 'real', True),
('rg_album_peak', 'real', True),
('original_year', 'int', True),
('original_month', 'int', True),
('original_day', 'int', True),
]
ALBUM_KEYS = [f[0] for f in ALBUM_FIELDS]
ALBUM_KEYS_ITEM = [f[0] for f in ALBUM_FIELDS if f[2]]

View file

@ -928,26 +928,6 @@ class MediaFile(object):
etc = StorageStyle('GROUPING'),
asf = StorageStyle('WM/ContentGroupDescription'),
)
year = MediaField(out_type=int,
mp3 = StorageStyle('TDRC', packing=packing.DATE, pack_pos=0),
mp4 = StorageStyle("\xa9day", packing=packing.DATE, pack_pos=0),
etc = [StorageStyle('DATE', packing=packing.DATE, pack_pos=0),
StorageStyle('YEAR')],
asf = StorageStyle('WM/Year', packing=packing.DATE, pack_pos=0),
)
month = MediaField(out_type=int,
mp3 = StorageStyle('TDRC', packing=packing.DATE, pack_pos=1),
mp4 = StorageStyle("\xa9day", packing=packing.DATE, pack_pos=1),
etc = StorageStyle('DATE', packing=packing.DATE, pack_pos=1),
asf = StorageStyle('WM/Year', packing=packing.DATE, pack_pos=1),
)
day = MediaField(out_type=int,
mp3 = StorageStyle('TDRC', packing=packing.DATE, pack_pos=2),
mp4 = StorageStyle("\xa9day", packing=packing.DATE, pack_pos=2),
etc = StorageStyle('DATE', packing=packing.DATE, pack_pos=2),
asf = StorageStyle('WM/Year', packing=packing.DATE, pack_pos=2),
)
date = CompositeDateField(year, month, day)
track = MediaField(out_type=int,
mp3 = StorageStyle('TRCK', packing=packing.SLASHED, pack_pos=0),
mp4 = StorageStyle('trkn', packing=packing.TUPLE, pack_pos=0),
@ -1101,6 +1081,56 @@ class MediaFile(object):
asf = StorageStyle('MusicBrainz/Album Comment'),
)
# Release date.
year = MediaField(out_type=int,
mp3 = StorageStyle('TDRC', packing=packing.DATE, pack_pos=0),
mp4 = StorageStyle("\xa9day", packing=packing.DATE, pack_pos=0),
etc = [StorageStyle('DATE', packing=packing.DATE, pack_pos=0),
StorageStyle('YEAR')],
asf = StorageStyle('WM/Year', packing=packing.DATE, pack_pos=0),
)
month = MediaField(out_type=int,
mp3 = StorageStyle('TDRC', packing=packing.DATE, pack_pos=1),
mp4 = StorageStyle("\xa9day", packing=packing.DATE, pack_pos=1),
etc = StorageStyle('DATE', packing=packing.DATE, pack_pos=1),
asf = StorageStyle('WM/Year', packing=packing.DATE, pack_pos=1),
)
day = MediaField(out_type=int,
mp3 = StorageStyle('TDRC', packing=packing.DATE, pack_pos=2),
mp4 = StorageStyle("\xa9day", packing=packing.DATE, pack_pos=2),
etc = StorageStyle('DATE', packing=packing.DATE, pack_pos=2),
asf = StorageStyle('WM/Year', packing=packing.DATE, pack_pos=2),
)
date = CompositeDateField(year, month, day)
# *Original* release date.
original_year = MediaField(out_type=int,
mp3 = StorageStyle('TDOR', packing=packing.DATE, pack_pos=0),
mp4 = StorageStyle('----:com.apple.iTunes:ORIGINAL YEAR',
packing=packing.DATE, pack_pos=0),
etc = StorageStyle('ORIGINALDATE', packing=packing.DATE, pack_pos=0),
asf = StorageStyle('WM/OriginalReleaseYear', packing=packing.DATE,
pack_pos=0),
)
original_month = MediaField(out_type=int,
mp3 = StorageStyle('TDOR', packing=packing.DATE, pack_pos=1),
mp4 = StorageStyle('----:com.apple.iTunes:ORIGINAL YEAR',
packing=packing.DATE, pack_pos=1),
etc = StorageStyle('ORIGINALDATE', packing=packing.DATE, pack_pos=1),
asf = StorageStyle('WM/OriginalReleaseYear', packing=packing.DATE,
pack_pos=1),
)
original_day = MediaField(out_type=int,
mp3 = StorageStyle('TDOR', packing=packing.DATE, pack_pos=2),
mp4 = StorageStyle('----:com.apple.iTunes:ORIGINAL YEAR',
packing=packing.DATE, pack_pos=2),
etc = StorageStyle('ORIGINALDATE', packing=packing.DATE, pack_pos=2),
asf = StorageStyle('WM/OriginalReleaseYear', packing=packing.DATE,
pack_pos=2),
)
original_date = CompositeDateField(original_year, original_month,
original_day)
# Nonstandard metadata.
artist_credit = MediaField(
mp3 = StorageStyle('TXXX', id3_desc=u'Artist Credit'),

View file

@ -30,13 +30,16 @@ Other new stuff:
* Support for Windows Media/ASF audio files. Thanks to Dave Hayes.
* New :doc:`/plugins/smartplaylist`: generate and maintain m3u playlist files
based on beets queries. Thanks to Dang Mai Hai.
* Two new plugin events were added: *database_change* and *cli_exit*. Thanks
again to Dang Mai Hai.
* ReplayGain tags on MPEG-4/AAC files are now supported. And, even more
astonishingly, ReplayGain values in MP3 and AAC files are now compatible with
`iTunes Sound Check`_. Thanks to Dave Hayes.
* Track titles in the importer UI's difference display are now either aligned
vertically or broken across two lines for readability. Thanks to Tai Lee.
* Albums and items have new fields reflecting the *original* release date
(``original_year``, ``original_month``, and ``original_day``). Previously,
when tagging from MusicBrainz, *only* the original date was stored; now, the
old fields refer to the *specific* release date (e.g., when the album was
reissued).
* Some changes to the way candidates are recommended for selection, thanks to
Tai Lee:
@ -67,6 +70,8 @@ Other new stuff:
highlighted.
* The importer UI no longer shows a change when the track length difference is
less than 10 seconds. (This threshold was previously 2 seconds.)
* Two new plugin events were added: *database_change* and *cli_exit*. Thanks
again to Dang Mai Hai.
* Plugins are now loaded in the order they appear in the config file. Thanks to
Dang Mai Hai.
* :doc:`/plugins/bpd`: Browse by album artist and album artist sort name.

View file

@ -170,10 +170,9 @@ Ordinary metadata:
* genre
* composer
* grouping
* year
* month
* day
* track
* year, month, day: The release date of the specific release.
* original_year, original_month, original_day: The release date of the original
version of the album.
* tracktotal
* disc
* disctotal

Binary file not shown.

View file

@ -95,7 +95,8 @@ class MBAlbumInfoTest(unittest.TestCase):
self.assertEqual(d.album_id, 'ALBUM ID')
self.assertEqual(d.artist, 'ARTIST NAME')
self.assertEqual(d.artist_id, 'ARTIST ID')
self.assertEqual(d.year, 1984)
self.assertEqual(d.original_year, 1984)
self.assertEqual(d.year, 3001)
self.assertEqual(d.artist_credit, 'ARTIST CREDIT')
def test_parse_release_type(self):
@ -106,9 +107,9 @@ class MBAlbumInfoTest(unittest.TestCase):
def test_parse_release_full_date(self):
release = self._make_release('1987-03-31')
d = mb.album_info(release)
self.assertEqual(d.year, 1987)
self.assertEqual(d.month, 3)
self.assertEqual(d.day, 31)
self.assertEqual(d.original_year, 1987)
self.assertEqual(d.original_month, 3)
self.assertEqual(d.original_day, 31)
def test_parse_tracks(self):
tracks = [self._make_track('TITLE ONE', 'ID ONE', 100.0 * 1000.0),
@ -174,8 +175,8 @@ class MBAlbumInfoTest(unittest.TestCase):
def test_parse_release_year_month_only(self):
release = self._make_release('1987-03')
d = mb.album_info(release)
self.assertEqual(d.year, 1987)
self.assertEqual(d.month, 3)
self.assertEqual(d.original_year, 1987)
self.assertEqual(d.original_month, 3)
def test_no_durations(self):
tracks = [self._make_track('TITLE', 'ID', None)]
@ -186,9 +187,9 @@ class MBAlbumInfoTest(unittest.TestCase):
def test_no_release_date(self):
release = self._make_release(None)
d = mb.album_info(release)
self.assertFalse(d.year)
self.assertFalse(d.month)
self.assertFalse(d.day)
self.assertFalse(d.original_year)
self.assertFalse(d.original_month)
self.assertFalse(d.original_day)
def test_various_artists_defaults_false(self):
release = self._make_release(None)

View file

@ -120,6 +120,10 @@ CORRECT_DICTS = {
'albumdisambig': u'',
'artist_credit': u'',
'albumartist_credit': u'',
'original_year': 0,
'original_month': 0,
'original_day': 0,
'original_date': datetime.date.min,
},
# Full release date.