Add duplicate_keys feature for singletons

This commit is contained in:
Julien Cassette 2022-01-22 22:36:47 +01:00
parent f50d250c4a
commit 7633465734
4 changed files with 48 additions and 14 deletions

View file

@ -27,7 +27,9 @@ import:
group_albums: no
pretend: false
search_ids: []
duplicate_keys: albumartist album
duplicate_keys:
album: albumartist album
single: artist title
duplicate_action: ask
bell: no
set_fields: {}

View file

@ -676,7 +676,7 @@ class ImportTask(BaseImportTask):
duplicates = []
task_paths = {i.path for i in self.items if i}
keys = config['import']['duplicate_keys'].as_str_seq()
keys = config['import']['duplicate_keys']['album'].as_str_seq()
info['albumartist'] = info['artist']
# Create an Album object so that flexible attributes can be used.
tmp_album = library.Album(lib, **info)
@ -893,12 +893,17 @@ class SingletonImportTask(ImportTask):
self.is_album = False
self.paths = [item.path]
def chosen_ident(self):
assert self.choice_flag in (action.ASIS, action.APPLY, action.RETAG)
def chosen_info(self):
"""Return a dictionary of metadata about the current choice.
May only be called when the choice flag is ASIS or RETAG
(in which case the data comes from the files' current metadata)
or APPLY (in which case the data comes from the choice).
"""
assert self.choice_flag in (action.ASIS, action.RETAG, action.APPLY)
if self.choice_flag in (action.ASIS, action.RETAG):
return (self.item.artist, self.item.title)
return dict(self.item)
elif self.choice_flag is action.APPLY:
return (self.match.info.artist, self.match.info.title)
return self.match.info.copy()
def imported_items(self):
return [self.item]
@ -919,14 +924,14 @@ class SingletonImportTask(ImportTask):
"""Return a list of items from `lib` that have the same artist
and title as the task.
"""
artist, title = self.chosen_ident()
info = self.chosen_info()
found_items = []
query = dbcore.AndQuery((
dbcore.MatchQuery('artist', artist),
dbcore.MatchQuery('title', title),
))
for other_item in lib.items(query):
keys = config['import']['duplicate_keys']['single'].as_str_seq()
# Create an Item object so that flexible attributes can be used.
tmp_item = library.Item(lib, **info)
for other_item in tmp_item.duplicates(*keys):
# Existing items not considered duplicates.
if other_item.path != self.item.path:
found_items.append(other_item)

View file

@ -607,6 +607,20 @@ class Item(LibModel):
i.mtime = i.current_mtime() # Initial mtime.
return i
@classmethod
def construct_match_queries(cls, **info):
subqueries = []
for (key, value) in info.items():
# Use slow queries for flexible attributes.
fast = key in cls._fields
subqueries.append(dbcore.MatchQuery(key, value, fast))
return subqueries
def duplicates(self, *keys):
info = {key: self.get(key) for key in keys}
subqueries = self.construct_match_queries(**info)
return self._db.items(dbcore.AndQuery(subqueries))
def __setitem__(self, key, value):
"""Set the item's value for a standard field or a flexattr."""
# Encode unicode paths and read buffers.

View file

@ -1242,7 +1242,7 @@ class ImportDuplicateAlbumTest(unittest.TestCase, TestHelper,
# Create import session
self.importer = self.create_importer()
config['import']['autotag'] = True
config['import']['duplicate_keys'] = 'albumartist album'
config['import']['duplicate_keys']['album'] = 'albumartist album'
def tearDown(self):
self.teardown_beets()
@ -1313,7 +1313,7 @@ class ImportDuplicateAlbumTest(unittest.TestCase, TestHelper,
self.skipTest('write me')
def test_keep_when_extra_key_is_different(self):
config['import']['duplicate_keys'] = 'albumartist album flex'
config['import']['duplicate_keys']['album'] = 'albumartist album flex'
item = self.lib.items().get()
import_file = MediaFile(os.path.join(
@ -1359,6 +1359,7 @@ class ImportDuplicateSingletonTest(unittest.TestCase, TestHelper,
self.importer = self.create_importer()
config['import']['autotag'] = True
config['import']['singletons'] = True
config['import']['duplicate_keys']['single'] = 'artist title'
def tearDown(self):
self.teardown_beets()
@ -1395,6 +1396,18 @@ class ImportDuplicateSingletonTest(unittest.TestCase, TestHelper,
item = self.lib.items().get()
self.assertEqual(item.mb_trackid, 'old trackid')
def test_keep_when_extra_key_is_different(self):
config['import']['duplicate_keys']['single'] = 'artist title flex'
item = self.lib.items().get()
item.flex = 'different'
item.store()
self.assertEqual(len(self.lib.items()), 1)
self.importer.default_resolution = self.importer.Resolution.SKIP
self.importer.run()
self.assertEqual(len(self.lib.items()), 2)
def test_twice_in_import_dir(self):
self.skipTest('write me')