diff --git a/NEWS b/NEWS index 5c50a1e4f..3569bc832 100644 --- a/NEWS +++ b/NEWS @@ -30,6 +30,7 @@ * Fixed bug that completely broke non-autotagged imports ("import -A"). * Fixed bug that logged the wrong paths when using "import -l". * Fixed autotagging for the creatively-named band !!!. +* Fixed normalization of relative paths. * Efficiency tweak should reduce the number of MusicBrainz queries per autotagged album. * A new "-v" command line switch enables debugging output. diff --git a/beets/autotag/__init__.py b/beets/autotag/__init__.py index 66fc47d96..a247ec5c0 100644 --- a/beets/autotag/__init__.py +++ b/beets/autotag/__init__.py @@ -55,8 +55,8 @@ RECOMMEND_STRONG = 'RECOMMEND_STRONG' RECOMMEND_MEDIUM = 'RECOMMEND_MEDIUM' RECOMMEND_NONE = 'RECOMMEND_NONE' # Thresholds for recommendations. -STRONG_REC_THRESH = 0.03 -MEDIUM_REC_THRESH = 0.2 +STRONG_REC_THRESH = 0.04 +MEDIUM_REC_THRESH = 0.25 REC_GAP_THRESH = 0.25 # Parameters for string distance function. @@ -66,16 +66,15 @@ SD_END_WORDS = ['the', 'a', 'an'] SD_PATTERNS = [ (r'^the ', 0.1), (r'[\[\(]?(ep|single)[\]\)]?', 0.0), - (r'[\[\(]?(featuring|feat|ft)[\. :]', 0.3), + (r'[\[\(]?(featuring|feat|ft)[\. :].+', 0.1), (r'\(.*?\)', 0.3), (r'\[.*?\]', 0.3), + (r'(, )?(pt\.|part) .+', 0.2), ] # Autotagging exceptions. class AutotagError(Exception): pass -class InsufficientMetadataError(AutotagError): - pass # Global logger. log = logging.getLogger('beets') @@ -197,7 +196,9 @@ def string_dist(str1, str2): # the current case), recalculate the distances for the # modified strings. case_dist = _string_dist_basic(case_str1, case_str2) - case_delta = max(0, base_dist - case_dist) + case_delta = max(0.0, base_dist - case_dist) + if case_delta == 0.0: + continue # Shift our baseline strings down (to avoid rematching the # same part of the string) and add a scaled distance @@ -468,6 +469,7 @@ def tag_album(items, search_artist=None, search_album=None): """ # Get current metadata. cur_artist, cur_album = current_metadata(items) + log.debug('Tagging %s - %s' % (cur_artist, cur_album)) # The output result tuples (keyed by MB album ID). out_tuples = {} @@ -482,20 +484,22 @@ def tag_album(items, search_artist=None, search_album=None): # matches. rec = recommendation(out_tuples) if rec == RECOMMEND_STRONG: - log.debug('ID match for %s - %s.' % (cur_artist, cur_album)) + log.debug('ID match.') return cur_artist, cur_album, out_tuples.values(), rec # Search terms. if not (search_artist and search_album): # No explicit search terms -- use current metadata. search_artist, search_album = cur_artist, cur_album + log.debug('Search terms: %s - %s' % (search_artist, search_album)) # Get candidate metadata from search. - if not search_artist or not search_album: - raise InsufficientMetadataError() - candidates = mb.match_album(search_artist, search_album, - len(items), MAX_CANDIDATES) - candidates = list(candidates) + if search_artist and search_album: + candidates = mb.match_album(search_artist, search_album, + len(items), MAX_CANDIDATES) + candidates = list(candidates) + else: + candidates = [] # Get candidates from plugins. candidates.extend(plugins.candidates(items)) diff --git a/beets/library.py b/beets/library.py index 4e89dee34..421d34894 100644 --- a/beets/library.py +++ b/beets/library.py @@ -283,6 +283,8 @@ class Item(object): """ if read_path is None: read_path = self.path + else: + read_path = _normpath(read_path) f = MediaFile(read_path) for key in ITEM_KEYS_META: diff --git a/beets/ui/commands.py b/beets/ui/commands.py index 63b3e1ec6..7503fbc40 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -211,7 +211,7 @@ def choose_match(path, items, cur_artist, cur_album, candidates, print_("No match found for:", path) sel = ui.input_options( "[U]se as-is, Skip, Enter manual search, or aBort?", - ('u', 's', 'e'), 'u', + ('u', 's', 'e', 'b'), 'u', 'Enter U, S, E, or B:' ) if sel == 'u': diff --git a/beetsplug/lastid.py b/beetsplug/lastid.py index f77340953..99622b520 100644 --- a/beetsplug/lastid.py +++ b/beetsplug/lastid.py @@ -85,7 +85,7 @@ class LastIdPlugin(BeetsPlugin): dist, dist_max = 0.0, 0.0 # Track title distance. - dist += autotag._ie_dist(last_data['title'], + dist += autotag.string_dist(last_data['title'], info['title']) \ * autotag.TRACK_TITLE_WEIGHT dist_max += autotag.TRACK_TITLE_WEIGHT @@ -108,7 +108,7 @@ class LastIdPlugin(BeetsPlugin): # Compare artist to MusicBrainz metadata. dist, dist_max = 0.0, 0.0 - dist += autotag._ie_dist(last_artist, info['artist']) \ + dist += autotag.string_dist(last_artist, info['artist']) \ * autotag.ARTIST_WEIGHT dist_max += autotag.ARTIST_WEIGHT diff --git a/test/test_autotag.py b/test/test_autotag.py index 466b84d29..29e950eb0 100644 --- a/test/test_autotag.py +++ b/test/test_autotag.py @@ -305,6 +305,10 @@ class StringDistanceTest(unittest.TestCase): autotag.string_dist('(EP)', '(EP)') autotag.string_dist(', An', '') + def test_heuristic_does_not_harm_distance(self): + dist = autotag.string_dist('Untitled', '[Untitled]') + self.assertEqual(dist, 0.0) + def suite(): return unittest.TestLoader().loadTestsFromName(__name__)