change search to use kwargs with value lists as search queries

This commit is contained in:
Johannes Knutsen 2010-08-09 09:46:31 +02:00
parent b9a7ed5ec6
commit 9d628eefb7
6 changed files with 67 additions and 53 deletions

View File

@ -312,14 +312,18 @@ class BaseLibraryController(object):
""" """
raise NotImplementedError raise NotImplementedError
def search(self, query): def search(self, **query):
""" """
Search the library for tracks where ``field`` contains ``query``. Search the library for tracks where ``field`` contains ``values``.
:param field: 'track', 'artist', 'album', 'uri', and 'any' Examples::
:type field: string
:param query: the search query search(any=['a']) # Returns results matching 'a'
:type query: string search(artist=['xyz']) # Returns results matching artist 'xyz'
search(any=['a', 'b'], artist=['xyz']) # Returns results matching 'a' and 'b' and artist 'xyz'
:param query: one or more queries to search for
:type query: dict
:rtype: :class:`mopidy.models.Playlist` :rtype: :class:`mopidy.models.Playlist`
""" """
raise NotImplementedError raise NotImplementedError

View File

@ -58,15 +58,18 @@ class DespotifyLibraryController(BaseLibraryController):
track = self.backend.spotify.lookup(uri.encode(ENCODING)) track = self.backend.spotify.lookup(uri.encode(ENCODING))
return DespotifyTranslator.to_mopidy_track(track) return DespotifyTranslator.to_mopidy_track(track)
def search(self, query): def search(self, **query):
spotify_query = [] spotify_query = []
for (field, what) in query: for (field, values) in query.iteritems():
if field == u'track': if not hasattr(values, '__iter__'):
field = u'title' values = [values]
if field is u'any': for value in values:
spotify_query.append(what) if field == u'track':
else: field = u'title'
spotify_query.append(u'%s:"%s"' % (field, what)) if field is u'any':
spotify_query.append(value)
else:
spotify_query.append(u'%s:"%s"' % (field, value))
spotify_query = u' '.join(query) spotify_query = u' '.join(query)
result = self.backend.spotify.search(spotify_query.encode(ENCODING)) result = self.backend.spotify.search(spotify_query.encode(ENCODING))
if (result is None or result.playlist.tracks[0].get_uri() == if (result is None or result.playlist.tracks[0].get_uri() ==

View File

@ -30,7 +30,7 @@ class DummyLibraryController(BaseLibraryController):
if matches: if matches:
return matches[0] return matches[0]
def search(self, query): def search(self, **query):
return Playlist() return Playlist()
find_exact = search find_exact = search

View File

@ -236,35 +236,34 @@ class GStreamerLibraryController(BaseLibraryController):
result_tracks = filter(filter_func, result_tracks) result_tracks = filter(filter_func, result_tracks)
return Playlist(tracks=result_tracks) return Playlist(tracks=result_tracks)
def search(self, query): def search(self, **query):
for (field, what) in query:
if not what:
raise LookupError('Missing query')
result_tracks = self._uri_mapping.values() result_tracks = self._uri_mapping.values()
for (field, what) in query: for (field, values) in query:
q = what.strip().lower() if not hasattr(values, '__iter__'):
values = [values]
for value in values:
q = value.strip().lower()
# FIXME this is bound to be slow for large libraries # FIXME this is bound to be slow for large libraries
track_filter = lambda t: q in t.name.lower() track_filter = lambda t: q in t.name.lower()
album_filter = lambda t: q in getattr(t, 'album', Album()).name.lower() album_filter = lambda t: q in getattr(t, 'album', Album()).name.lower()
artist_filter = lambda t: filter(lambda a: q in a.name.lower(), artist_filter = lambda t: filter(lambda a: q in a.name.lower(),
t.artists) t.artists)
uri_filter = lambda t: q in t.uri.lower() uri_filter = lambda t: q in t.uri.lower()
any_filter = lambda t: track_filter(t) or album_filter(t) or \ any_filter = lambda t: track_filter(t) or album_filter(t) or \
artist_filter(t) or uri_filter(t) artist_filter(t) or uri_filter(t)
if field == 'track': if field == 'track':
result_tracks = filter(track_filter, result_tracks) result_tracks = filter(track_filter, result_tracks)
elif field == 'album': elif field == 'album':
result_tracks = filter(album_filter, result_tracks) result_tracks = filter(album_filter, result_tracks)
elif field == 'artist': elif field == 'artist':
result_tracks = filter(artist_filter, result_tracks) result_tracks = filter(artist_filter, result_tracks)
elif field == 'uri': elif field == 'uri':
result_tracks = filter(uri_filter, result_tracks) result_tracks = filter(uri_filter, result_tracks)
elif field == 'any': elif field == 'any':
result_tracks = filter(any_filter, result_tracks) result_tracks = filter(any_filter, result_tracks)
else: else:
raise LookupError('Invalid lookup field: %s' % field) raise LookupError('Invalid lookup field: %s' % field)
return Playlist(tracks=result_tracks) return Playlist(tracks=result_tracks)

View File

@ -69,13 +69,18 @@ class LibspotifyLibraryController(BaseLibraryController):
spotify_track = Link.from_string(uri).as_track() spotify_track = Link.from_string(uri).as_track()
return LibspotifyTranslator.to_mopidy_track(spotify_track) return LibspotifyTranslator.to_mopidy_track(spotify_track)
def search(self, query): def search(self, **query):
spotify_query = [] spotify_query = []
for (field, what) in query: for (field, values) in query.iteritems():
if field is u'any': if not hasattr(values, '__iter__'):
spotify_query.append(what) values = [values]
else: for value in values:
spotify_query.append(u'%s:"%s"' % (field, what)) if field == u'track':
field = u'title'
if field is u'any':
spotify_query.append(value)
else:
spotify_query.append(u'%s:"%s"' % (field, value))
spotify_query = u' '.join(spotify_query) spotify_query = u' '.join(spotify_query)
logger.debug(u'In search method, search for: %s' % spotify_query) logger.debug(u'In search method, search for: %s' % spotify_query)
my_end, other_end = multiprocessing.Pipe() my_end, other_end = multiprocessing.Pipe()

View File

@ -118,14 +118,17 @@ class MpdFrontend(object):
query_part_pattern = ( query_part_pattern = (
r'"?(?P<field>([Aa]lbum|[Aa]rtist|[Ff]ilename|[Tt]itle|[Aa]ny))"?\s' r'"?(?P<field>([Aa]lbum|[Aa]rtist|[Ff]ilename|[Tt]itle|[Aa]ny))"?\s'
r'"(?P<what>[^"]+)"') r'"(?P<what>[^"]+)"')
query = [] query = {}
for query_part in query_parts: for query_part in query_parts:
m = re.match(query_part_pattern, query_part) m = re.match(query_part_pattern, query_part)
field = m.groupdict()['field'].lower() field = m.groupdict()['field'].lower()
if field == u'title': if field == u'title':
field = u'track' field = u'track'
what = m.groupdict()['what'].lower() what = m.groupdict()['what'].lower()
query.append((field, what)) if field in query:
query[field].append(what)
else:
query[field] = [what]
return query return query
@handle_pattern(r'^disableoutput "(?P<outputid>\d+)"$') @handle_pattern(r'^disableoutput "(?P<outputid>\d+)"$')
@ -646,7 +649,7 @@ class MpdFrontend(object):
- capitalizes the type argument. - capitalizes the type argument.
""" """
query = self._build_query(mpd_query) query = self._build_query(mpd_query)
return self.backend.library.find_exact(query).mpd_format() return self.backend.library.find_exact(**query).mpd_format()
@handle_pattern(r'^findadd ' @handle_pattern(r'^findadd '
r'(?P<query>("?([Aa]lbum|[Aa]rtist|[Ff]ilename|[Tt]itle|[Aa]ny)"? "[^"]+"\s?)+)$') r'(?P<query>("?([Aa]lbum|[Aa]rtist|[Ff]ilename|[Tt]itle|[Aa]ny)"? "[^"]+"\s?)+)$')
@ -722,7 +725,7 @@ class MpdFrontend(object):
return artists return artists
def __music_db_list_album_artist(self, artist): def __music_db_list_album_artist(self, artist):
playlist = self.backend.library.find_exact([(u'artist', artist)]) playlist = self.backend.library.find_exact(artist=[artist])
albums = set() albums = set()
for track in playlist.tracks: for track in playlist.tracks:
albums.add((u'Album', track.album.name)) albums.add((u'Album', track.album.name))
@ -810,7 +813,7 @@ class MpdFrontend(object):
- capitalizes the field argument. - capitalizes the field argument.
""" """
query = self._build_query(mpd_query) query = self._build_query(mpd_query)
return self.backend.library.search(query).mpd_format() return self.backend.library.search(**query).mpd_format()
@handle_pattern(r'^update( "(?P<uri>[^"]+)")*$') @handle_pattern(r'^update( "(?P<uri>[^"]+)")*$')
def _music_db_update(self, uri=None, rescan_unmodified_files=False): def _music_db_update(self, uri=None, rescan_unmodified_files=False):