reorder items() and albums() parameters to reflect common use

This commit is contained in:
Adrian Sampson 2011-05-05 17:20:24 -07:00
parent 151df84150
commit 8341dee3ab
7 changed files with 36 additions and 158 deletions

View file

@ -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

View file

@ -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))

View file

@ -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

View file

@ -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):

View file

@ -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]

View file

@ -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

View file

@ -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.