diff --git a/beets/importer.py b/beets/importer.py index 6d800a1e5a..f37d5261e1 100644 --- a/beets/importer.py +++ b/beets/importer.py @@ -521,28 +521,18 @@ def skip(self): # Convenient data. - def chosen_ident(self): - """Returns identifying metadata about the current choice. For - albums, this is an (artist, album) pair. For items, this is - (artist, title). 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 (data comes from the choice). - """ - if self.choice_flag in (action.ASIS, action.RETAG): - return (self.cur_artist, self.cur_album) - elif self.choice_flag is action.APPLY: - return (self.match.info.artist, self.match.info.album) - def chosen_info(self): - """Returns a dictionnary of metadata about the current choice. + """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.cur_info + likelies, consensus = autotag.current_metadata(self.items) + return likelies elif self.choice_flag is action.APPLY: - return self.match.info + return self.match.info.copy() def imported_items(self): """Return a list of Items that should be added to the library. @@ -667,8 +657,6 @@ def lookup_candidates(self): candidate IDs are stored in self.search_ids: if present, the initial lookup is restricted to only those IDs. """ - likelies, consensus = autotag.current_metadata(self.items) - self.cur_info = likelies artist, album, prop = \ autotag.tag_album(self.items, search_ids=self.search_ids) self.cur_artist = artist @@ -680,24 +668,19 @@ def find_duplicates(self, lib): """Return a list of albums from `lib` with the same artist and album name as the task. """ - artist, album = self.chosen_ident() + info = self.chosen_info() - if artist is None: + if info['artist'] is None: # As-is import with no artist. Skip check. return [] duplicates = [] task_paths = {i.path for i in self.items if i} - keys = config['import']['duplicate_keys'].as_str().split() - info = self.chosen_info().copy() - info['albumartist'] = artist - album = library.Album(None, **info) - subqueries = [] - for key in keys: - value = album.get(key) - fast = key in library.Album.item_keys - subqueries.append(dbcore.MatchQuery(key, value, fast)) - duplicate_query = dbcore.AndQuery(subqueries) + keys = config['import']['duplicate_keys'].as_str_seq() + info['albumartist'] = info['artist'] + # Create an Album object so that flexible attributes can be used. + tmp_album = library.Album(None, **info) + duplicate_query = tmp_album.construct_duplicates_query(*keys) for album in lib.albums(duplicate_query): # Check whether the album paths are all present in the task diff --git a/beets/library.py b/beets/library.py index c8993f85ba..675ce37f6d 100644 --- a/beets/library.py +++ b/beets/library.py @@ -1142,6 +1142,20 @@ def _getters(cls): getters['albumtotal'] = Album._albumtotal return getters + @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 construct_duplicates_query(self, *keys): + info = {key: self.get(key) for key in keys} + subqueries = self.construct_match_queries(**info) + return dbcore.AndQuery(subqueries) + def items(self): """Return an iterable over the items associated with this album. diff --git a/docs/changelog.rst b/docs/changelog.rst index 2ce0d35e8f..462567e108 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -11,7 +11,7 @@ New features: * :doc:`/plugins/kodiupdate`: Now supports multiple kodi instances :bug:`4101` * Add the item fields ``bitrate_mode``, ``encoder_info`` and ``encoder_settings``. -* Allow to configure which fields are used to find duplicates +* :doc:`/reference/config`: Allow to configure which fields are used to find duplicates Bug fixes: diff --git a/docs/reference/config.rst b/docs/reference/config.rst index 448eb8e60c..d12fec6488 100644 --- a/docs/reference/config.rst +++ b/docs/reference/config.rst @@ -676,7 +676,7 @@ duplicate_keys ~~~~~~~~~~~~~~ The fields used to find duplicates in import task. -If several items have the same value for each key, they will be considered duplicates. +If several albums have the same value for each key, they will be considered duplicates. Default: ``albumartist album``