diff --git a/beets/autotag/distance.py b/beets/autotag/distance.py index d5821f4733..ba6d7939bf 100644 --- a/beets/autotag/distance.py +++ b/beets/autotag/distance.py @@ -35,7 +35,7 @@ SD_PATTERNS = [ (r"^the ", 0.1), (r"[\[\(]?(ep|single)[\]\)]?", 0.0), - (r"[\[\(]?(featuring|feat|ft)[\. :].+", 0.1), + (r"[\[\(]?\b(featuring|feat|ft)\b[\. :].+", 0.1), (r"\(.*?\)", 0.3), (r"\[.*?\]", 0.3), (r"(, )?(pt\.|part) .+", 0.2), diff --git a/docs/changelog.rst b/docs/changelog.rst index 096a35a6db..f4fadcdb78 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -95,6 +95,10 @@ Bug fixes valid date/time string" error instead of crashing with an uncaught ``KeyError``. A ``|`` was being accepted as a relative-date unit due to a regular expression character-class typo. +- Autotagging distance calculations no longer treat ordinary words containing + "ft" (such as "draft", "left", "gift", "craft") as a "featuring artist" + suffix, which was silently making genuinely different titles/artists score as + near-identical matches. .. For plugin developers diff --git a/test/autotag/test_distance.py b/test/autotag/test_distance.py index 15c4a7208f..03c2513c77 100644 --- a/test/autotag/test_distance.py +++ b/test/autotag/test_distance.py @@ -282,6 +282,23 @@ def test_matching_distance(self, string1, string2): def test_different_distance(self): assert string_dist("Some String", "Totally Different") != 0.0 + @pytest.mark.parametrize( + "string1, string2", + [ + ("Draft Beer", "Draft Whiskey"), + ("Left Field", "Left Symphony"), + ("Gift Ideas", "Gift Cards"), + ("Craft Beer", "Craft Wine"), + ], + ) + def test_featuring_pattern_does_not_match_mid_word(self, string1, string2): + # The "featuring"/"feat"/"ft" pattern must not match "ft" embedded + # inside an ordinary word (draft, left, gift, craft, ...) -- doing so + # would treat everything after "ft" as a low-weight suffix and make + # genuinely different strings look almost identical instead of + # correctly registering as a large distance. + assert string_dist(string1, string2) > 0.3 + @pytest.mark.parametrize( "string1, string2, reference", [