mirror of
https://github.com/beetbox/beets.git
synced 2026-01-25 09:38:19 +01:00
explicit searching for VA releases when it seems likely
This commit is contained in:
parent
effc338957
commit
f256726917
3 changed files with 40 additions and 10 deletions
|
|
@ -74,6 +74,9 @@ SD_PATTERNS = [
|
||||||
(r'(, )?(pt\.|part) .+', 0.2),
|
(r'(, )?(pt\.|part) .+', 0.2),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Artist signals that indicate "various artists".
|
||||||
|
VA_ARTISTS = (u'', u'various artists', u'va', u'unknown')
|
||||||
|
|
||||||
# Autotagging exceptions.
|
# Autotagging exceptions.
|
||||||
class AutotagError(Exception):
|
class AutotagError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
@ -230,7 +233,7 @@ def _plurality(objs):
|
||||||
max_freq = freq
|
max_freq = freq
|
||||||
res = obj
|
res = obj
|
||||||
|
|
||||||
return res
|
return res, len(freqs) <= 1
|
||||||
|
|
||||||
def current_metadata(items):
|
def current_metadata(items):
|
||||||
"""Returns the most likely artist and album for a set of Items.
|
"""Returns the most likely artist and album for a set of Items.
|
||||||
|
|
@ -238,10 +241,11 @@ def current_metadata(items):
|
||||||
"""
|
"""
|
||||||
keys = 'artist', 'album'
|
keys = 'artist', 'album'
|
||||||
likelies = {}
|
likelies = {}
|
||||||
|
consensus = {}
|
||||||
for key in keys:
|
for key in keys:
|
||||||
values = [getattr(item, key) for item in items]
|
values = [getattr(item, key) for item in items]
|
||||||
likelies[key] = _plurality(values)
|
likelies[key], consensus[key] = _plurality(values)
|
||||||
return likelies['artist'], likelies['album']
|
return likelies['artist'], likelies['album'], consensus['artist']
|
||||||
|
|
||||||
def order_items(items, trackinfo):
|
def order_items(items, trackinfo):
|
||||||
"""Orders the items based on how they match some canonical track
|
"""Orders the items based on how they match some canonical track
|
||||||
|
|
@ -325,7 +329,7 @@ def distance(items, info):
|
||||||
"""Determines how "significant" an album metadata change would be.
|
"""Determines how "significant" an album metadata change would be.
|
||||||
Returns a float in [0.0,1.0]. The list of items must be ordered.
|
Returns a float in [0.0,1.0]. The list of items must be ordered.
|
||||||
"""
|
"""
|
||||||
cur_artist, cur_album = current_metadata(items)
|
cur_artist, cur_album, _ = current_metadata(items)
|
||||||
cur_artist = cur_artist or ''
|
cur_artist = cur_artist or ''
|
||||||
cur_album = cur_album or ''
|
cur_album = cur_album or ''
|
||||||
|
|
||||||
|
|
@ -492,7 +496,7 @@ def tag_album(items, search_artist=None, search_album=None):
|
||||||
May raise an AutotagError if existing metadata is insufficient.
|
May raise an AutotagError if existing metadata is insufficient.
|
||||||
"""
|
"""
|
||||||
# Get current metadata.
|
# Get current metadata.
|
||||||
cur_artist, cur_album = current_metadata(items)
|
cur_artist, cur_album, artist_consensus = current_metadata(items)
|
||||||
log.debug('Tagging %s - %s' % (cur_artist, cur_album))
|
log.debug('Tagging %s - %s' % (cur_artist, cur_album))
|
||||||
|
|
||||||
# The output result tuples (keyed by MB album ID).
|
# The output result tuples (keyed by MB album ID).
|
||||||
|
|
@ -525,6 +529,14 @@ def tag_album(items, search_artist=None, search_album=None):
|
||||||
else:
|
else:
|
||||||
candidates = []
|
candidates = []
|
||||||
|
|
||||||
|
# Possibly add "various artists" search.
|
||||||
|
if search_album and ((not artist_consensus) or \
|
||||||
|
(search_artist.lower() in VA_ARTISTS) or \
|
||||||
|
any(item.comp for item in items)):
|
||||||
|
log.debug('Possibly Various Artists; adding matches.')
|
||||||
|
candidates.extend(mb.match_album(None, search_album, len(items),
|
||||||
|
MAX_CANDIDATES))
|
||||||
|
|
||||||
# Get candidates from plugins.
|
# Get candidates from plugins.
|
||||||
candidates.extend(plugins.candidates(items))
|
candidates.extend(plugins.candidates(items))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,12 @@ def match_album(artist, album, tracks=None, limit=SEARCH_LIMIT):
|
||||||
optionally, a number of tracks on the album.
|
optionally, a number of tracks on the album.
|
||||||
"""
|
"""
|
||||||
# Build search criteria.
|
# Build search criteria.
|
||||||
criteria = {'artist': artist, 'release': album}
|
criteria = {'release': album}
|
||||||
|
if artist is not None:
|
||||||
|
criteria['artist'] = artist
|
||||||
|
else:
|
||||||
|
# Various Artists search.
|
||||||
|
criteria['arid'] = VARIOUS_ARTISTS_ID
|
||||||
if tracks is not None:
|
if tracks is not None:
|
||||||
criteria['tracks'] = str(tracks)
|
criteria['tracks'] = str(tracks)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,26 +28,39 @@ from beets.library import Item
|
||||||
class PluralityTest(unittest.TestCase):
|
class PluralityTest(unittest.TestCase):
|
||||||
def test_plurality_consensus(self):
|
def test_plurality_consensus(self):
|
||||||
objs = [1, 1, 1, 1]
|
objs = [1, 1, 1, 1]
|
||||||
obj = autotag._plurality(objs)
|
obj, consensus = autotag._plurality(objs)
|
||||||
self.assertEqual(obj, 1)
|
self.assertEqual(obj, 1)
|
||||||
|
self.assertTrue(consensus)
|
||||||
|
|
||||||
def test_plurality_near_consensus(self):
|
def test_plurality_near_consensus(self):
|
||||||
objs = [1, 1, 2, 1]
|
objs = [1, 1, 2, 1]
|
||||||
obj = autotag._plurality(objs)
|
obj, consensus = autotag._plurality(objs)
|
||||||
self.assertEqual(obj, 1)
|
self.assertEqual(obj, 1)
|
||||||
|
self.assertFalse(consensus)
|
||||||
|
|
||||||
def test_plurality_conflict(self):
|
def test_plurality_conflict(self):
|
||||||
objs = [1, 1, 2, 2, 3]
|
objs = [1, 1, 2, 2, 3]
|
||||||
obj = autotag._plurality(objs)
|
obj, consensus = autotag._plurality(objs)
|
||||||
self.assert_(obj in (1, 2))
|
self.assert_(obj in (1, 2))
|
||||||
|
self.assertFalse(consensus)
|
||||||
|
|
||||||
def test_current_metadata_finds_pluralities(self):
|
def test_current_metadata_finds_pluralities(self):
|
||||||
items = [Item({'artist': 'The Beetles', 'album': 'The White Album'}),
|
items = [Item({'artist': 'The Beetles', 'album': 'The White Album'}),
|
||||||
Item({'artist': 'The Beatles', 'album': 'The White Album'}),
|
Item({'artist': 'The Beatles', 'album': 'The White Album'}),
|
||||||
Item({'artist': 'The Beatles', 'album': 'Teh White Album'})]
|
Item({'artist': 'The Beatles', 'album': 'Teh White Album'})]
|
||||||
l_artist, l_album = autotag.current_metadata(items)
|
l_artist, l_album, artist_consensus = autotag.current_metadata(items)
|
||||||
self.assertEqual(l_artist, 'The Beatles')
|
self.assertEqual(l_artist, 'The Beatles')
|
||||||
self.assertEqual(l_album, 'The White Album')
|
self.assertEqual(l_album, 'The White Album')
|
||||||
|
self.assertFalse(artist_consensus)
|
||||||
|
|
||||||
|
def test_current_metadata_artist_consensus(self):
|
||||||
|
items = [Item({'artist': 'The Beatles', 'album': 'The White Album'}),
|
||||||
|
Item({'artist': 'The Beatles', 'album': 'The White Album'}),
|
||||||
|
Item({'artist': 'The Beatles', 'album': 'Teh White Album'})]
|
||||||
|
l_artist, l_album, artist_consensus = autotag.current_metadata(items)
|
||||||
|
self.assertEqual(l_artist, 'The Beatles')
|
||||||
|
self.assertEqual(l_album, 'The White Album')
|
||||||
|
self.assertTrue(artist_consensus)
|
||||||
|
|
||||||
class AlbumDistanceTest(unittest.TestCase):
|
class AlbumDistanceTest(unittest.TestCase):
|
||||||
def item(self, title, track, artist='some artist'):
|
def item(self, title, track, artist='some artist'):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue