From 064a0432f10e5bd295c7ea1bf9681590da361f32 Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Mon, 10 Oct 2011 21:31:47 -0700 Subject: [PATCH] further refactoring: abstract source from matching logic --HG-- rename : beets/autotag/model.py => beets/autotag/hooks.py --- beets/autotag/__init__.py | 5 +++-- beets/autotag/{model.py => hooks.py} | 21 ++++++++++++++++++++- beets/autotag/match.py | 23 ++++++++--------------- beets/autotag/mb.py | 5 +++-- 4 files changed, 34 insertions(+), 20 deletions(-) rename beets/autotag/{model.py => hooks.py} (85%) diff --git a/beets/autotag/__init__.py b/beets/autotag/__init__.py index cd8b47481..d2d444fbc 100644 --- a/beets/autotag/__init__.py +++ b/beets/autotag/__init__.py @@ -18,15 +18,16 @@ import os from beets import library, mediafile from beets.util import sorted_walk +from . import mb # Parts of external interface. -from .model import AlbumInfo, TrackInfo +from .hooks import AlbumInfo, TrackInfo from .match import tag_item, tag_album from .match import RECOMMEND_STRONG, RECOMMEND_MEDIUM, RECOMMEND_NONE from .match import STRONG_REC_THRESH, MEDIUM_REC_THRESH, REC_GAP_THRESH -# Main interface. +# Additional utilities for the main interface. def albums_in_dir(path): """Recursively searches the given directory and returns an iterable diff --git a/beets/autotag/model.py b/beets/autotag/hooks.py similarity index 85% rename from beets/autotag/model.py rename to beets/autotag/hooks.py index 64318e892..b6da29a9d 100644 --- a/beets/autotag/model.py +++ b/beets/autotag/hooks.py @@ -12,7 +12,11 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -"""Classes used by metadata sources and the matching logic.""" +"""Glue between metadata sources and the matching logic.""" + +from . import mb + +# Classes used to represent candidate options. class AlbumInfo(object): """Describes a canonical release that may be used to match a release @@ -68,3 +72,18 @@ class TrackInfo(object): self.artist = artist self.artist_id = artist self.length = length + + +# Aggregation of sources. + +def _album_for_id(album_id): + return mb.album_for_id(album_id) + +def _match_album(artist, album, tracks): + return mb.match_album(artist, album, tracks) + +def _track_for_id(track_id): + return mb.track_for_id(track_id) + +def _match_track(artist, title): + return mb.match_track(artist, title) diff --git a/beets/autotag/match.py b/beets/autotag/match.py index edc364f1b..49e245e8a 100644 --- a/beets/autotag/match.py +++ b/beets/autotag/match.py @@ -20,9 +20,9 @@ import re from munkres import Munkres from unidecode import unidecode -from beets.autotag import mb from beets import plugins from beets.util import levenshtein, plurality +from beets.autotag import hooks # Distance parameters. # Text distance weights: proportions on the normalized intuitive edit @@ -64,12 +64,6 @@ SD_REPLACE = [ (r'&', 'and'), ] -# Try 5 releases. In the future, this should be more dynamic: let the -# probability of continuing to the next release be inversely -# proportional to how good our current best is and how long we've -# already taken. -MAX_CANDIDATES = 5 - # Recommendation constants. RECOMMEND_STRONG = 'RECOMMEND_STRONG' RECOMMEND_MEDIUM = 'RECOMMEND_MEDIUM' @@ -304,7 +298,7 @@ def match_by_id(items): if bool(reduce(lambda x,y: x if x==y else (), albumids)): albumid = albumids[0] log.debug('Searching for discovered album ID: ' + albumid) - return mb.album_for_id(albumid) + return hooks._album_for_id(albumid) else: log.debug('No album ID consensus.') return None @@ -398,7 +392,7 @@ def tag_album(items, timid=False, search_artist=None, search_album=None, # Try to find album indicated by MusicBrainz IDs. if search_id: log.debug('Searching for album ID: ' + search_id) - id_info = mb.album_for_id(search_id) + id_info = hooks._album_for_id(search_id) else: id_info = match_by_id(items) if id_info: @@ -428,8 +422,8 @@ def tag_album(items, timid=False, search_artist=None, search_album=None, # Get candidate metadata from search. if search_artist and search_album: - candidates = mb.match_album(search_artist, search_album, - len(items), MAX_CANDIDATES) + candidates = hooks._match_album(search_artist, search_album, + len(items)) candidates = list(candidates) else: candidates = [] @@ -439,8 +433,7 @@ def tag_album(items, timid=False, search_artist=None, search_album=None, (search_artist.lower() in VA_ARTISTS) or \ any(item.comp for item in items)): log.debug(u'Possibly Various Artists; adding matches.') - candidates.extend(mb.match_album(None, search_album, len(items), - MAX_CANDIDATES)) + candidates.extend(hooks._match_album(None, search_album, len(items))) # Get candidates from plugins. candidates.extend(plugins.candidates(items)) @@ -471,7 +464,7 @@ def tag_item(item, timid=False, search_artist=None, search_title=None, trackid = search_id or item.mb_trackid if trackid: log.debug('Searching for track ID: ' + trackid) - track_info = mb.track_for_id(trackid) + track_info = hooks._track_for_id(trackid) if track_info: dist = track_distance(item, track_info, incl_artist=True) candidates.append((dist, track_info)) @@ -494,7 +487,7 @@ def tag_item(item, timid=False, search_artist=None, search_title=None, log.debug(u'Item search terms: %s - %s' % (search_artist, search_title)) # Candidate metadata from search. - for track_info in mb.match_track(search_artist, search_title): + for track_info in hooks._match_track(search_artist, search_title): dist = track_distance(item, track_info, incl_artist=True) candidates.append((dist, track_info)) diff --git a/beets/autotag/mb.py b/beets/autotag/mb.py index bd0d5cae3..1aa3d8a6f 100644 --- a/beets/autotag/mb.py +++ b/beets/autotag/mb.py @@ -30,9 +30,10 @@ from musicbrainz2.model import Release from threading import Lock from musicbrainz2.model import VARIOUS_ARTISTS_ID -SEARCH_LIMIT = 10 +SEARCH_LIMIT = 5 VARIOUS_ARTISTS_ID = VARIOUS_ARTISTS_ID.rsplit('/', 1)[1] + class ServerBusyError(Exception): pass class BadResponseError(Exception): pass @@ -298,7 +299,7 @@ def match_album(artist, album, tracks=None, limit=SEARCH_LIMIT): criteria['tracks'] = str(tracks) # Search for the release. - return find_releases(criteria) + return find_releases(criteria, limit) def match_track(artist, title): """Searches for a single track and returns an iterable of track