diff --git a/beets/importer.py b/beets/importer.py index 3feaffcb8..6dbd82ad8 100644 --- a/beets/importer.py +++ b/beets/importer.py @@ -65,7 +65,7 @@ def _duplicate_check(lib, task): found_albums = [] cur_paths = set(i.path for i in task.items if i) - for album_cand in lib.albums(artist=artist): + for album_cand in lib.albums(library.MatchQuery('albumartist', artist)): if album_cand.album == album: # Check whether the album is identical in contents, in which # case it is not a duplicate (will be replaced). @@ -83,7 +83,11 @@ def _item_duplicate_check(lib, task): artist, title = task.chosen_ident() found_items = [] - for other_item in lib.items(artist=artist, title=title): + query = library.AndQuery(( + library.MatchQuery('artist', artist), + library.MatchQuery('title', title), + )) + for other_item in lib.items(query): # Existing items not considered duplicates. if other_item.path == task.item.path: continue @@ -296,7 +300,7 @@ class ImportSession(object): def resolve_duplicate(self, task): raise NotImplementedError - + def choose_item(self, task): raise NotImplementedError @@ -533,7 +537,7 @@ def read_tasks(session): if resume_dir: # Either accept immediately or prompt for input to decide. - if _resume() == True: + if _resume() is True: do_resume = True log.warn('Resuming interrupted import of %s' % path) else: @@ -746,7 +750,9 @@ def apply_choices(session): # when the last item is removed. task.replaced_items = defaultdict(list) for item in items: - dup_items = session.lib.items(library.MatchQuery('path', item.path)) + dup_items = session.lib.items( + library.MatchQuery('path', item.path) + ) for dup_item in dup_items: task.replaced_items[item].append(dup_item) log.debug('replacing item %i: %s' % diff --git a/beets/library.py b/beets/library.py index e48b632d8..53a7a71f8 100644 --- a/beets/library.py +++ b/beets/library.py @@ -1508,58 +1508,42 @@ class Library(object): # Querying. - def albums(self, query=None, artist=None): - """Returns a sorted list of Album objects, possibly filtered - by an artist name or an arbitrary query. Unqualified query - string terms only match fields that apply at an album - granularity: artist, album, and genre. + def _fetch(self, model_cls, order_by, query): + """Fetch the objects of type `model_cls` matching the given + query. The query may be given as a string, string sequence, a + Query object, or None (to fetch everything). """ - query = get_query(query, True) - if artist is not None: - # "Add" the artist to the query. - query = AndQuery((query, MatchQuery('albumartist', artist))) + query = get_query(query, model_cls is Album) where, subvals = query.clause() with self.transaction() as tx: rows = tx.query( - "SELECT * FROM albums WHERE {0} " - "ORDER BY {1}, album".format( - where or '1', - _orelse("albumartist_sort", "albumartist"), - ), - subvals, - ) - - return Results(Album, rows, self, None if where else query) - - def items(self, query=None, artist=None, album=None, title=None): - """Returns a sequence of the items matching the given artist, - album, title, and query (if present). Sorts in such a way as to - group albums appropriately. Unqualified query string terms only - match intuitively relevant fields: artist, album, genre, title, - and comments. - """ - queries = [get_query(query, False)] - if artist is not None: - queries.append(MatchQuery('artist', artist)) - if album is not None: - queries.append(MatchQuery('album', album)) - if title is not None: - queries.append(MatchQuery('title', title)) - query = AndQuery(queries) - where, subvals = query.clause() - - with self.transaction() as tx: - rows = tx.query( - "SELECT * FROM items WHERE {0} " - "ORDER BY {1}, album, disc, track".format( - where or '1', - _orelse("artist_sort", "artist"), + "SELECT * FROM {table} WHERE {where} " + "ORDER BY {order_by}".format( + table=model_cls._table, + where=where or '1', + order_by=order_by ), subvals ) - return Results(Item, rows, self, None if where else query) + return Results(model_cls, rows, self, None if where else query) + + def albums(self, query=None): + """Get a sorted list of Album objects matching the given query. + """ + order = '{0}, album'.format( + _orelse("albumartist_sort", "albumartist") + ) + return self._fetch(Album, order, query) + + def items(self, query=None): + """Get a sorted list of Item objects matching the given query. + """ + order = '{0}, album'.format( + _orelse("artist_sort", "artist") + ) + return self._fetch(Item, order, query) # Convenience accessors. @@ -1932,7 +1916,7 @@ class DefaultTemplateFunctions(object): for key in keys: value = getattr(album, key) subqueries.append(MatchQuery(key, value)) - albums = self.lib.albums(query=AndQuery(subqueries)) + albums = self.lib.albums(AndQuery(subqueries)) # If there's only one album to matching these details, then do # nothing. diff --git a/beetsplug/random.py b/beetsplug/random.py index 57ac77e79..259cbe5f6 100644 --- a/beetsplug/random.py +++ b/beetsplug/random.py @@ -32,9 +32,9 @@ def random_item(lib, opts, args): template = Template(fmt) if fmt else None if opts.album: - objs = list(lib.albums(query=query)) + objs = list(lib.albums(query)) else: - objs = list(lib.items(query=query)) + objs = list(lib.items(query)) if opts.equal_chance: # Group the objects by artist so we can sample from them.