Watchlist: stop treating different decimal-volume albums as duplicates (Sokhi — the real bug)
Sokhi's log showed the actual cause: with the wishlist "allow duplicates" toggle
on, is_track_missing_from_library skips a track when _albums_likely_match() says
the wanted album and a library album are the same — and it was matching albums
that differ ONLY by a decimal volume number:
[AllowDup] Album match — skipping (wanted: '...Vol.5', library: '...Vol.5.5')
[AllowDup] Album match — skipping (wanted: '...Vol.5.5', library: '...Vol.4.5')
His character-song CDs share track titles across volumes, so tracks from albums
he DOESN'T have got skipped because a same-titled track sits in a similarly-named
volume he DOES have — the partially-filled discography never completed.
Root cause: _normalize_album_for_match strips the dot ("Vol.5.5" -> "vol 5 5"),
and _VOLUME_MARKER_RE captured only a single trailing digit, so Vol.5, Vol.5.5
and Vol.4.5 all reduced to marker "5" and the volume-disagreement guard never
fired. Fix: capture the full multi-part number ((\d+(?:\s+\d+)*)) so "5" / "5 5"
/ "4 5" are distinct and the guard correctly rejects the match.
(Not lookback — the log confirms lookback=all was already honored.)
Tests: decimal/multi-part volumes (incl. the real CJK names) now block the
match; identical decimal volumes + naming-drift cases still match. 111 watchlist
tests pass.
This commit is contained in:
parent
13dca2dea6
commit
e6bf7c26de
2 changed files with 37 additions and 1 deletions
|
|
@ -354,8 +354,15 @@ def _normalize_album_for_match(name: str) -> str:
|
|||
return cleaned
|
||||
|
||||
|
||||
# Capture the FULL trailing number, including multi-part / decimal volumes.
|
||||
# Normalization strips the dot in "Vol.5.5" to "vol 5 5", so without the
|
||||
# `(?:\s+\d+)*` the extractor grabbed only the last "5" — making "Vol.5",
|
||||
# "Vol.5.5" and "Vol.4.5" all look like volume "5" and collapse together. That
|
||||
# made the watchlist treat tracks from different character-song CD volumes as
|
||||
# duplicates and skip them (Sokhi: partially-filled discography never completed).
|
||||
_VOLUME_MARKER_RE = re.compile(
|
||||
r'\b(?:vol(?:ume)?|pt|part|disc|book|chapter|episode)\.?\s*(\d+)\b|\b(\d+)\s*$',
|
||||
r'\b(?:vol(?:ume)?|pt|part|disc|book|chapter|episode)\.?\s*(\d+(?:\s+\d+)*)\b'
|
||||
r'|\b(\d+(?:\s+\d+)*)\s*$',
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -239,3 +239,32 @@ def test_agreeing_volume_markers_still_match(spotify_name, lib_name) -> None:
|
|||
"""Same volume marker should NOT block a match that other rules accept."""
|
||||
assert _albums_likely_match(spotify_name, lib_name)
|
||||
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"spotify_name,lib_name",
|
||||
[
|
||||
# Decimal / multi-part volume numbers must be distinguished — the dot is
|
||||
# stripped to a space in normalization, and grabbing only the last digit
|
||||
# made these collapse to the same marker (Sokhi: character-song CDs).
|
||||
("Character CD Vol.5", "Character CD Vol.5.5"),
|
||||
("Character CD Vol.5.5", "Character CD Vol.4.5"),
|
||||
("Anime OST Vol.1.5", "Anime OST Vol.2.5"),
|
||||
# The real CJK album names from the report.
|
||||
("TVアニメ「【推しの子】」キャラクターソングCD Vol.5",
|
||||
"TVアニメ「【推しの子】」キャラクターソングCD Vol.5.5"),
|
||||
],
|
||||
)
|
||||
def test_decimal_volume_markers_block_match(spotify_name, lib_name) -> None:
|
||||
assert not _albums_likely_match(spotify_name, lib_name)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"spotify_name,lib_name",
|
||||
[
|
||||
("Character CD Vol.5.5", "Character CD Vol.5.5"), # identical decimal vol
|
||||
("Character CD Vol.5.5", "Character CD Vol.5.5 (Deluxe)"),
|
||||
],
|
||||
)
|
||||
def test_same_decimal_volume_still_matches(spotify_name, lib_name) -> None:
|
||||
assert _albums_likely_match(spotify_name, lib_name)
|
||||
|
|
|
|||
Loading…
Reference in a new issue