From 69772cdc6da3b471d8ebf27ec3a51df149f57441 Mon Sep 17 00:00:00 2001 From: chuenchen309 <48723787+chuenchen309@users.noreply.github.com> Date: Thu, 16 Jul 2026 08:13:00 +0800 Subject: [PATCH 1/4] fix(autotag): "featuring" pattern in string_dist matches mid-word "ft" SD_PATTERNS' featuring/feat/ft regex has no word boundary before the alternation, so it matches "ft" embedded in ordinary words like "draft", "left", "gift", "craft" and treats everything after it as a low-weight suffix. "Draft Beer" vs. "Draft Whiskey" scores 0.05 (near-identical) instead of correctly registering as very different. --- beets/autotag/distance.py | 2 +- docs/changelog.rst | 4 ++++ test/autotag/test_distance.py | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/beets/autotag/distance.py b/beets/autotag/distance.py index d5821f4733..6d57cfd60d 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)[\. :].+", 0.1), (r"\(.*?\)", 0.3), (r"\[.*?\]", 0.3), (r"(, )?(pt\.|part) .+", 0.2), diff --git a/docs/changelog.rst b/docs/changelog.rst index bfb97468d7..4f7815fdc1 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -129,6 +129,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", [ From 8518a13f3d390b5ff287266190c9a6db891f5a57 Mon Sep 17 00:00:00 2001 From: chuenchen309 <48723787+chuenchen309@users.noreply.github.com> Date: Thu, 16 Jul 2026 18:11:30 +0800 Subject: [PATCH 2/4] docs: reflow changelog entry to satisfy docstrfmt Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/changelog.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 4f7815fdc1..fafbfc7afe 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -131,8 +131,8 @@ Bug fixes 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. + suffix, which was silently making genuinely different titles/artists score as + near-identical matches. .. For plugin developers From 19d0914401c26965abeb79a29f97936b456d016c Mon Sep 17 00:00:00 2001 From: chuenchen309 <48723787+chuenchen309@users.noreply.github.com> Date: Thu, 16 Jul 2026 18:42:15 +0800 Subject: [PATCH 3/4] fix(autotag): make featuring word boundary symmetric Apply reviewer suggestion (@snejus): add a trailing \b after the (featuring|feat|ft) alternation so the boundary is explicit on both sides, matching the leading \b. Co-Authored-By: Claude Opus 4.8 (1M context) --- beets/autotag/distance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beets/autotag/distance.py b/beets/autotag/distance.py index 6d57cfd60d..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"[\[\(]?\b(featuring|feat|ft)[\. :].+", 0.1), + (r"[\[\(]?\b(featuring|feat|ft)\b[\. :].+", 0.1), (r"\(.*?\)", 0.3), (r"\[.*?\]", 0.3), (r"(, )?(pt\.|part) .+", 0.2), From b5019fb180ba7b3a8ffa3a2d3ce52933bf903141 Mon Sep 17 00:00:00 2001 From: Sebastian Mohr Date: Thu, 30 Jul 2026 12:56:37 +0200 Subject: [PATCH 4/4] Moved changelog entry into unreleased section. --- docs/changelog.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index fafbfc7afe..87187cc716 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -23,6 +23,10 @@ Bug fixes digits no longer restarts the numbering: ``track.10.mp3`` now yields ``track.11.mp3`` instead of ``track.1.mp3``. The counter was matched with ``\.(\d)+$``, which captures only the final digit. +- 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 @@ -129,10 +133,6 @@ 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