diff --git a/beets/importer.py b/beets/importer.py index e2a34c097..06c193f91 100644 --- a/beets/importer.py +++ b/beets/importer.py @@ -95,7 +95,7 @@ def _duplicate_check(lib, artist, album, recent=None): recent.add((artist, album)) # Look in the library. - for album_cand in lib.albums(artist): + for album_cand in lib.albums(artist=artist): if album_cand.album == album: return True diff --git a/beets/library.py b/beets/library.py index 3bfe979bb..dc9020d63 100644 --- a/beets/library.py +++ b/beets/library.py @@ -917,7 +917,7 @@ class Library(BaseLibrary): # Querying. - def albums(self, artist=None, query=None): + def albums(self, query=None, artist=None): query = self._get_query(query, ALBUM_DEFAULT_FIELDS) if artist is not None: # "Add" the artist to the query. @@ -929,7 +929,7 @@ class Library(BaseLibrary): c = self.conn.execute(sql, subvals) return [Album(self, dict(res)) for res in c.fetchall()] - def items(self, artist=None, album=None, title=None, query=None): + def items(self, query=None, artist=None, album=None, title=None): queries = [self._get_query(query, ITEM_DEFAULT_FIELDS)] if artist is not None: queries.append(MatchQuery('artist', artist)) diff --git a/beets/ui/commands.py b/beets/ui/commands.py index 4fcc810ab..868c73480 100755 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -552,10 +552,10 @@ def list_items(lib, query, album): albums instead of single items. """ if album: - for album in lib.albums(query=query): + for album in lib.albums(query): print_(album.albumartist + u' - ' + album.album) else: - for item in lib.items(query=query): + for item in lib.items(query): print_(item.artist + u' - ' + item.album + u' - ' + item.title) list_cmd = ui.Subcommand('list', help='query the library', aliases=('ls',)) @@ -575,12 +575,12 @@ def remove_items(lib, query, album, delete=False): """ # Get the matching items. if album: - albums = list(lib.albums(query=query)) + albums = list(lib.albums(query)) items = [] for al in albums: items += al.items() else: - items = list(lib.items(query=query)) + items = list(lib.items(query)) if not items: print_('No matching items found.') @@ -626,7 +626,7 @@ default_commands.append(remove_cmd) def show_stats(lib, query): """Shows some statistics about the matched items.""" - items = lib.items(query=query) + items = lib.items(query) total_size = 0 total_time = 0.0 diff --git a/beetsplug/bpd/__init__.py b/beetsplug/bpd/__init__.py index fb8158363..77db61a05 100644 --- a/beetsplug/bpd/__init__.py +++ b/beetsplug/bpd/__init__.py @@ -966,7 +966,7 @@ class Server(BaseServer): query = self._metadata_query(beets.library.SubstringQuery, beets.library.AnySubstringQuery, kv) - for item in self.lib.items(query=query): + for item in self.lib.items(query): yield self._item_info(item) def cmd_find(self, conn, *kv): @@ -974,7 +974,7 @@ class Server(BaseServer): query = self._metadata_query(beets.library.MatchQuery, None, kv) - for item in self.lib.items(query=query): + for item in self.lib.items(query): yield self._item_info(item) def cmd_list(self, conn, show_tag, *kv): diff --git a/beetsplug/device.py b/beetsplug/device.py deleted file mode 100644 index f3a3dae43..000000000 --- a/beetsplug/device.py +++ /dev/null @@ -1,122 +0,0 @@ -# This file is part of beets. -# Copyright 2010, Adrian Sampson. -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. - -import os -import sys -import socket -import locale -import gpod - -from beets.library import BaseLibrary, Item -from beets.plugins import BeetsPlugin -import beets.ui - -FIELD_MAP = { - 'artist': 'artist', - 'title': 'title', - 'BPM': 'bpm', - 'genre': 'genre', - 'album': 'album', - 'cd_nr': 'disc', - 'cds': 'disctotal', - 'track_nr': 'track', - 'tracks': 'tracktotal', -} - -def track_to_item(track): - data = {} - for dname, bname in FIELD_MAP.items(): - data[bname] = track[dname] - data['length'] = float(track['tracklen']) / 1000 - data['path'] = track.ipod_filename() - return Item(data) - -class PodLibrary(BaseLibrary): - def __init__(self, path): - self.db = gpod.Database(path) - self.syncing = False - - @classmethod - def by_name(cls, name): - return cls(os.path.join(os.path.expanduser('~'), '.gvfs', name)) - - def _start_sync(self): - # Make sure we have a version of libgpod with these - # iPhone-specific functions. - if self.syncing: - return - if hasattr(gpod, 'itdb_start_sync'): - gpod.itdb_start_sync(self.db._itdb) - self.syncing = True - - def _stop_sync(self): - if not self.syncing: - return - if hasattr(gpod, 'itdb_stop_sync'): - gpod.itdb_stop_sync(self.db._itdb) - self.syncing = False - - def add(self, item): - self._start_sync() - track = self.db.new_Track() - track['userdata'] = { - 'transferred': 0, - 'hostname': socket.gethostname(), - 'charset': locale.getpreferredencoding(), - 'pc_mtime': os.stat(item.path).st_mtime, - } - track._set_userdata_utf8('filename', item.path.encode()) - for dname, bname in FIELD_MAP.items(): - track[dname] = getattr(item, bname) - track['tracklen'] = int(item.length * 1000) - self.db.copy_delayed_files() - - def get(self, query=None): - query = self._get_query(query) - for track in self.db: - item = track_to_item(track) - if query.match(item): - yield item - - def save(self): - self._stop_sync() - gpod.itdb_write(self.db._itdb, None) - - def load(self, item, load_id=None): - raise NotImplementedError - - def store(self, item, store_id=None, store_all=False): - raise NotImplementedError - - def remove(self, item): - raise NotImplementedError - - -# Plugin hook. - -class DevicePlugin(BeetsPlugin): - def commands(self): - cmd = beets.ui.Subcommand('dadd', help='add files to a device') - def func(lib, config, opts, args): - if not args: - raise beets.ui.UserError('no device name specified') - name = args.pop(0) - - items = lib.items(query=beets.ui.make_query(args)) - pod = PodLibrary.by_name(name) - for item in items: - pod.add(item) - pod.save() - cmd.func = func - return [cmd] diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index c123f4f29..d2d43d210 100755 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -65,7 +65,7 @@ class EmbedCoverArtPlugin(BeetsPlugin): # "embedart" command. def embed(lib, imagepath, query): - albums = lib.albums(query=query) + albums = lib.albums(query) for i_album in albums: album = i_album break @@ -79,7 +79,7 @@ def embed(lib, imagepath, query): # "extractart" command. def extract(lib, outpath, query): - items = lib.items(query=query) + items = lib.items(query) for i_item in items: item = i_item break @@ -111,7 +111,7 @@ def extract(lib, outpath, query): # "clearart" command. def clear(lib, query): log.info('Clearing album art from items:') - for item in lib.items(query=query): + for item in lib.items(query): log.info(u'%s - %s' % (item.artist, item.title)) mf = mediafile.MediaFile(syspath(item.path)) mf.art = None diff --git a/test/test_query.py b/test/test_query.py index ae2e043ab..7f158c19b 100644 --- a/test/test_query.py +++ b/test/test_query.py @@ -68,15 +68,15 @@ class AnySubstringQueryTest(unittest.TestCase): def test_no_restriction(self): q = beets.library.AnySubstringQuery('title') - self.assertEqual(self.lib.items(query=q).next().title, 'the title') + self.assertEqual(self.lib.items(q).next().title, 'the title') def test_restriction_completeness(self): q = beets.library.AnySubstringQuery('title', ['title']) - self.assertEqual(self.lib.items(query=q).next().title, 'the title') + self.assertEqual(self.lib.items(q).next().title, 'the title') def test_restriction_soundness(self): q = beets.library.AnySubstringQuery('title', ['artist']) - self.assertRaises(StopIteration, self.lib.items(query=q).next) + self.assertRaises(StopIteration, self.lib.items(q).next) # Convenient asserts for matching items. @@ -100,57 +100,57 @@ class GetTest(unittest.TestCase, AssertsMixin): def test_get_empty(self): q = '' - results = self.lib.items(query=q) + results = self.lib.items(q) self.assert_matched_all(results) def test_get_none(self): q = None - results = self.lib.items(query=q) + results = self.lib.items(q) self.assert_matched_all(results) def test_get_one_keyed_term(self): q = 'artist:Lil' - results = self.lib.items(query=q) + results = self.lib.items(q) self.assert_matched(results, 'Littlest Things') self.assert_done(results) def test_get_one_unkeyed_term(self): q = 'Terry' - results = self.lib.items(query=q) + results = self.lib.items(q) self.assert_matched(results, 'Boracay') self.assert_done(results) def test_get_no_matches(self): q = 'popebear' - results = self.lib.items(query=q) + results = self.lib.items(q) self.assert_done(results) def test_invalid_key(self): q = 'pope:bear' - results = self.lib.items(query=q) + results = self.lib.items(q) self.assert_matched_all(results) def test_term_case_insensitive(self): q = 'UNCoVER' - results = self.lib.items(query=q) + results = self.lib.items(q) self.assert_matched(results, 'Lovers Who Uncover') self.assert_done(results) def test_term_case_insensitive_with_key(self): q = 'album:stiLL' - results = self.lib.items(query=q) + results = self.lib.items(q) self.assert_matched(results, 'Littlest Things') self.assert_done(results) def test_key_case_insensitive(self): q = 'ArTiST:Allen' - results = self.lib.items(query=q) + results = self.lib.items(q) self.assert_matched(results, 'Littlest Things') self.assert_done(results) def test_unkeyed_term_matches_multiple_columns(self): q = 'little' - results = self.lib.items(query=q) + results = self.lib.items(q) self.assert_matched(results, 'Littlest Things') self.assert_matched(results, 'Lovers Who Uncover') self.assert_matched(results, 'Boracay') @@ -158,14 +158,14 @@ class GetTest(unittest.TestCase, AssertsMixin): def test_keyed_term_matches_only_one_column(self): q = 'artist:little' - results = self.lib.items(query=q) + results = self.lib.items(q) self.assert_matched(results, 'Lovers Who Uncover') self.assert_matched(results, 'Boracay') self.assert_done(results) def test_mulitple_terms_narrow_search(self): q = 'little ones' - results = self.lib.items(query=q) + results = self.lib.items(q) self.assert_matched(results, 'Lovers Who Uncover') self.assert_matched(results, 'Boracay') self.assert_done(results) @@ -184,25 +184,25 @@ class MemoryGetTest(unittest.TestCase, AssertsMixin): def test_singleton_true(self): q = 'singleton:true' - results = self.lib.items(query=q) + results = self.lib.items(q) self.assert_matched(results, 'singleton item') self.assert_done(results) def test_singleton_false(self): q = 'singleton:false' - results = self.lib.items(query=q) + results = self.lib.items(q) self.assert_matched(results, 'album item') self.assert_done(results) def test_compilation_true(self): q = 'comp:true' - results = self.lib.items(query=q) + results = self.lib.items(q) self.assert_matched(results, 'album item') self.assert_done(results) def test_compilation_false(self): q = 'comp:false' - results = self.lib.items(query=q) + results = self.lib.items(q) self.assert_matched(results, 'singleton item') self.assert_done(results) @@ -229,20 +229,20 @@ class BrowseTest(unittest.TestCase, AssertsMixin): self.assert_done(items) def test_albums_matches_album(self): - albums = list(self.lib.albums(query='person')) + albums = list(self.lib.albums('person')) self.assertEqual(len(albums), 1) def test_albums_matches_albumartist(self): - albums = list(self.lib.albums(query='panda')) + albums = list(self.lib.albums('panda')) self.assertEqual(len(albums), 1) def test_items_matches_title(self): - items = self.lib.items(query='boracay') + items = self.lib.items('boracay') self.assert_matched(items, 'Boracay') self.assert_done(items) def test_items_does_not_match_year(self): - items = self.lib.items(query='2007') + items = self.lib.items('2007') self.assert_done(items) #FIXME Haven't tested explicit (non-query) criteria.