mirror of
https://github.com/beetbox/beets.git
synced 2025-12-31 13:02:47 +01:00
reorder items() and albums() parameters to reflect common use
This commit is contained in:
parent
151df84150
commit
8341dee3ab
7 changed files with 36 additions and 158 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in a new issue