mirror of
https://github.com/beetbox/beets.git
synced 2026-02-19 22:03:05 +01:00
autotag: Can now compute the distance for incomplete albums
If the user has some songs from a specific album, but not all of them, the real solution is immediately discarded. This commit is the first of a series that will implement support for these incomplete albums. The point of this patch is to make sure missing commits are taken into account when calculating the distance between an album and its canonical data. Note that in order not to break API compatibility, the album_distance call for the plugins receives a purged version of both the items and the album info, resulting in some potential accuracy if the plugin bases itself on the index of a track in album_info.tracks.
This commit is contained in:
parent
78dca315d4
commit
4dc4025b5f
2 changed files with 36 additions and 5 deletions
|
|
@ -17,6 +17,7 @@ releases and tracks.
|
|||
"""
|
||||
import logging
|
||||
import re
|
||||
import copy
|
||||
from munkres import Munkres
|
||||
from unidecode import unidecode
|
||||
|
||||
|
|
@ -31,6 +32,8 @@ ARTIST_WEIGHT = 3.0
|
|||
ALBUM_WEIGHT = 3.0
|
||||
# The weight of the entire distance calculated for a given track.
|
||||
TRACK_WEIGHT = 1.0
|
||||
# The weight of a missing track.
|
||||
MISSING_WEIGHT = 0.3
|
||||
# These distances are components of the track distance (that is, they
|
||||
# compete against each other but not ARTIST_WEIGHT and ALBUM_WEIGHT;
|
||||
# the overall TRACK_WEIGHT does that).
|
||||
|
|
@ -161,7 +164,7 @@ def current_metadata(items):
|
|||
likelies = {}
|
||||
consensus = {}
|
||||
for key in keys:
|
||||
values = [getattr(item, key) for item in items]
|
||||
values = [getattr(item, key) for item in items if item]
|
||||
likelies[key], freq = plurality(values)
|
||||
consensus[key] = (freq == len(values))
|
||||
return likelies['artist'], likelies['album'], consensus['artist']
|
||||
|
|
@ -269,12 +272,25 @@ def distance(items, album_info):
|
|||
|
||||
# Track distances.
|
||||
for i, (item, track_info) in enumerate(zip(items, album_info.tracks)):
|
||||
dist += track_distance(item, track_info, i+1, album_info.va) * \
|
||||
TRACK_WEIGHT
|
||||
dist_max += TRACK_WEIGHT
|
||||
if item:
|
||||
dist += track_distance(item, track_info, i+1, album_info.va) * \
|
||||
TRACK_WEIGHT
|
||||
dist_max += TRACK_WEIGHT
|
||||
else:
|
||||
dist += MISSING_WEIGHT
|
||||
dist_max += MISSING_WEIGHT
|
||||
|
||||
# Plugin distances.
|
||||
plugin_d, plugin_dm = plugins.album_distance(items, album_info)
|
||||
# In order not to break compatibility, send purged lists
|
||||
purged_items, purged_tracks = [], []
|
||||
for i, t in zip(items, album_info.tracks):
|
||||
if i:
|
||||
purged_items.append(i)
|
||||
purged_tracks.append(t)
|
||||
purged_album_info = copy.copy(album_info)
|
||||
purged_album_info.tracks = purged_tracks
|
||||
|
||||
plugin_d, plugin_dm = plugins.album_distance(purged_items, purged_album_info)
|
||||
dist += plugin_d
|
||||
dist_max += plugin_dm
|
||||
|
||||
|
|
|
|||
|
|
@ -94,6 +94,21 @@ class AlbumDistanceTest(unittest.TestCase):
|
|||
)
|
||||
self.assertEqual(match.distance(items, info), 0)
|
||||
|
||||
def test_incomplete_album(self):
|
||||
items = []
|
||||
items.append(self.item('one', 1))
|
||||
items.append(self.item('three', 3))
|
||||
info = AlbumInfo(
|
||||
artist = 'some artist',
|
||||
album = 'some album',
|
||||
tracks = self.trackinfo(),
|
||||
va = False,
|
||||
album_id = None, artist_id = None,
|
||||
)
|
||||
self.assertNotEqual(match.distance(items, info), 0)
|
||||
# Make sure the distance is not too great
|
||||
self.assertTrue(match.distance(items, info) < 0.2)
|
||||
|
||||
def test_global_artists_differ(self):
|
||||
items = []
|
||||
items.append(self.item('one', 1))
|
||||
|
|
|
|||
Loading…
Reference in a new issue