mirror of
https://github.com/beetbox/beets.git
synced 2026-01-07 00:15:20 +01:00
Add duplicate_keys feature for singletons
This commit is contained in:
parent
f50d250c4a
commit
7633465734
4 changed files with 48 additions and 14 deletions
|
|
@ -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: {}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue