Skip to content

Commit b21c231

Browse files
a544jhclaude
andcommitted
Enable duplicate detection for as-is imports
When importing with autotag=no, duplicate detection was skipped entirely because the import_asis stage called _apply_choice() directly without first calling _resolve_duplicates(). This meant the duplicate_keys and duplicate_action config options were ignored for as-is imports. This was a known limitation documented by a FIXME comment added in commit 79d1203 (Sep 2014): "We should also resolve duplicates when not autotagging." The FIXME was later removed during a comment cleanup (f145e3b) but the issue was never addressed. This commit adds the _resolve_duplicates() call to import_asis, ensuring duplicate detection works consistently regardless of the autotag setting. This applies to both album imports and singleton imports. Test changes: - Renamed test_no_autotag_keeps_duplicate_album to test_no_autotag_removes_duplicate_album to verify the corrected behavior - Added test_no_autotag_removes_duplicate_singleton to verify singleton duplicate detection also works with autotag=no Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c04fc95 commit b21c231

2 files changed

Lines changed: 41 additions & 9 deletions

File tree

beets/importer/stages.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ def import_asis(session: ImportSession, task: ImportTask):
230230

231231
log.info("{}", displayable_path(task.paths))
232232
task.set_choice(Action.ASIS)
233+
_resolve_duplicates(session, task)
233234
_apply_choice(session, task)
234235

235236

test/test_importer.py

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -945,29 +945,34 @@ def test_remove_duplicate_album(self):
945945
item = self.lib.items().get()
946946
assert item.title == "new title"
947947

948-
def test_no_autotag_keeps_duplicate_album(self):
948+
def test_no_autotag_removes_duplicate_album(self):
949949
config["import"]["autotag"] = False
950+
album = self.lib.albums().get()
950951
item = self.lib.items().get()
951952
assert item.title == "t\xeftle 0"
952953
assert item.filepath.exists()
953954

954-
# Imported item has the same artist and album as the one in the
955-
# library.
955+
# Imported item has the same albumartist and album as the one in the
956+
# library album. We use album metadata (not item metadata) since
957+
# duplicate detection uses album-level fields.
956958
import_file = os.path.join(
957959
self.importer.paths[0], b"album", b"track_1.mp3"
958960
)
959961
import_file = MediaFile(import_file)
960-
import_file.artist = item["artist"]
961-
import_file.albumartist = item["artist"]
962-
import_file.album = item["album"]
962+
import_file.artist = album.albumartist
963+
import_file.albumartist = album.albumartist
964+
import_file.album = album.album
963965
import_file.title = "new title"
966+
import_file.save()
964967

965968
self.importer.default_resolution = self.importer.Resolution.REMOVE
966969
self.importer.run()
967970

968-
assert item.filepath.exists()
969-
assert len(self.lib.albums()) == 2
970-
assert len(self.lib.items()) == 2
971+
# Old duplicate should be removed, new one imported
972+
assert len(self.lib.albums()) == 1
973+
assert len(self.lib.items()) == 1
974+
# The new item should be in the library
975+
assert self.lib.items().get().title == "new title"
971976

972977
def test_keep_duplicate_album(self):
973978
self.importer.default_resolution = self.importer.Resolution.KEEPBOTH
@@ -1096,6 +1101,32 @@ def test_keep_when_extra_key_is_different(self):
10961101

10971102
assert len(self.lib.items()) == 2
10981103

1104+
def test_no_autotag_removes_duplicate_singleton(self):
1105+
config["import"]["autotag"] = False
1106+
item = self.lib.items().get()
1107+
assert item.mb_trackid == "old trackid"
1108+
assert item.filepath.exists()
1109+
1110+
# Imported item has the same artist and title as the one in the
1111+
# library. We use item metadata since duplicate detection uses
1112+
# item-level fields for singletons.
1113+
import_file = os.path.join(
1114+
self.importer.paths[0], b"album", b"track_1.mp3"
1115+
)
1116+
import_file = MediaFile(import_file)
1117+
import_file.artist = item.artist
1118+
import_file.title = item.title
1119+
import_file.mb_trackid = "new trackid"
1120+
import_file.save()
1121+
1122+
self.importer.default_resolution = self.importer.Resolution.REMOVE
1123+
self.importer.run()
1124+
1125+
# Old duplicate should be removed, new one imported
1126+
assert len(self.lib.items()) == 1
1127+
# The new item should be in the library
1128+
assert self.lib.items().get().mb_trackid == "new trackid"
1129+
10991130
def test_twice_in_import_dir(self):
11001131
self.skipTest("write me")
11011132

0 commit comments

Comments
 (0)