From eab399357f73047e21bc270d24e120d77699a9b6 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Mon, 19 Nov 2012 21:08:41 +0100 Subject: [PATCH] Make library.lookup() return a list of tracks --- docs/changes.rst | 4 ++++ mopidy/backends/dummy.py | 4 +--- mopidy/backends/local/library.py | 4 ++-- mopidy/backends/local/playlists.py | 2 +- mopidy/backends/spotify/library.py | 4 ++-- mopidy/core/library.py | 9 ++++++--- .../mpd/protocol/current_playlist.py | 20 ++++++++++++------- mopidy/frontends/mpris/objects.py | 11 ++++------ tests/backends/base/library.py | 8 ++++---- tests/core/library_test.py | 4 ++-- 10 files changed, 39 insertions(+), 31 deletions(-) diff --git a/docs/changes.rst b/docs/changes.rst index f024bc30..b45ae7c6 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -141,6 +141,10 @@ backends: - :meth:`mopidy.core.TracklistController.remove` can now remove multiple tracks, and returns the tracks it removed. +- :meth:`mopidy.core.LibraryController.lookup` now returns a list of tracks. + This makes it possible to support lookup of artist or album URIs which then + can expand to a list of tracks. + **Bug fixes** - :issue:`218`: The MPD commands ``listplaylist`` and ``listplaylistinfo`` now diff --git a/mopidy/backends/dummy.py b/mopidy/backends/dummy.py index 1d561bda..62ac8e8f 100644 --- a/mopidy/backends/dummy.py +++ b/mopidy/backends/dummy.py @@ -42,9 +42,7 @@ class DummyLibraryProvider(base.BaseLibraryProvider): return [] def lookup(self, uri): - matches = filter(lambda t: uri == t.uri, self.dummy_library) - if matches: - return matches[0] + return filter(lambda t: uri == t.uri, self.dummy_library) def refresh(self, uri=None): pass diff --git a/mopidy/backends/local/library.py b/mopidy/backends/local/library.py index 1b406f84..e0e6f423 100644 --- a/mopidy/backends/local/library.py +++ b/mopidy/backends/local/library.py @@ -30,10 +30,10 @@ class LocalLibraryProvider(base.BaseLibraryProvider): def lookup(self, uri): try: - return self._uri_mapping[uri] + return [self._uri_mapping[uri]] except KeyError: logger.debug('Failed to lookup %r', uri) - return None + return [] def find_exact(self, **query): self._validate_query(query) diff --git a/mopidy/backends/local/playlists.py b/mopidy/backends/local/playlists.py index ea45bcbb..666532c5 100644 --- a/mopidy/backends/local/playlists.py +++ b/mopidy/backends/local/playlists.py @@ -55,7 +55,7 @@ class LocalPlaylistsProvider(base.BasePlaylistsProvider): try: # TODO We must use core.library.lookup() to support tracks # from other backends - tracks.append(self.backend.library.lookup(track_uri)) + tracks += self.backend.library.lookup(track_uri) except LookupError as ex: logger.error('Playlist item could not be added: %s', ex) diff --git a/mopidy/backends/spotify/library.py b/mopidy/backends/spotify/library.py index 5d80bc8d..df04058b 100644 --- a/mopidy/backends/spotify/library.py +++ b/mopidy/backends/spotify/library.py @@ -57,10 +57,10 @@ class SpotifyLibraryProvider(base.BaseLibraryProvider): def lookup(self, uri): try: - return SpotifyTrack(uri) + return [SpotifyTrack(uri)] except SpotifyError as e: logger.debug('Failed to lookup "%s": %s', uri, e) - return None + return [] def refresh(self, uri=None): pass # TODO diff --git a/mopidy/core/library.py b/mopidy/core/library.py index ccd4e92b..c1a89222 100644 --- a/mopidy/core/library.py +++ b/mopidy/core/library.py @@ -41,17 +41,20 @@ class LibraryController(object): def lookup(self, uri): """ - Lookup track with given URI. Returns :class:`None` if not found. + Lookup the given URI. + + If the URI expands to multiple tracks, the returned list will contain + them all. :param uri: track URI :type uri: string - :rtype: :class:`mopidy.models.Track` or :class:`None` + :rtype: list of :class:`mopidy.models.Track` """ backend = self._get_backend(uri) if backend: return backend.library.lookup(uri).get() else: - return None + return [] def refresh(self, uri=None): """ diff --git a/mopidy/frontends/mpd/protocol/current_playlist.py b/mopidy/frontends/mpd/protocol/current_playlist.py index a1af4549..da950078 100644 --- a/mopidy/frontends/mpd/protocol/current_playlist.py +++ b/mopidy/frontends/mpd/protocol/current_playlist.py @@ -22,9 +22,9 @@ def add(context, uri): """ if not uri: return - track = context.core.library.lookup(uri).get() - if track: - context.core.tracklist.add(track) + tracks = context.core.library.lookup(uri).get() + if tracks: + context.core.tracklist.append(tracks) return raise MpdNoExistError('directory or file not found', command='add') @@ -52,13 +52,19 @@ def addid(context, uri, songpos=None): raise MpdNoExistError('No such song', command='addid') if songpos is not None: songpos = int(songpos) - track = context.core.library.lookup(uri).get() - if track is None: + tracks = context.core.library.lookup(uri).get() + if not tracks: raise MpdNoExistError('No such song', command='addid') if songpos and songpos > context.core.tracklist.length.get(): raise MpdArgError('Bad song index', command='addid') - tl_track = context.core.tracklist.add(track, at_position=songpos).get() - return ('Id', tl_track.tlid) + first_tl_track = None + for track in tracks: + tl_track = context.core.tracklist.add(track, at_position=songpos).get() + if songpos is not None: + songpos += 1 + if first_tl_track is None: + first_tl_track = tl_track + return ('Id', first_tl_track.tlid) @handle_request(r'^delete "(?P\d+):(?P\d+)*"$') diff --git a/mopidy/frontends/mpris/objects.py b/mopidy/frontends/mpris/objects.py index a66abdb5..51b0d7e8 100644 --- a/mopidy/frontends/mpris/objects.py +++ b/mopidy/frontends/mpris/objects.py @@ -279,13 +279,10 @@ class MprisObject(dbus.service.Object): return # NOTE Check if URI has MIME type known to the backend, if MIME support # is added to the backend. - uri_schemes = self.core.uri_schemes.get() - if not any([uri.startswith(uri_scheme) for uri_scheme in uri_schemes]): - return - track = self.core.library.lookup(uri).get() - if track is not None: - tl_track = self.core.tracklist.add(track).get() - self.core.playback.play(tl_track) + tracks = self.core.library.lookup(uri).get() + if tracks: + tl_tracks = self.core.tracklist.append(tracks).get() + self.core.playback.play(tl_tracks[0]) else: logger.debug('Track with URI "%s" not found in library.', uri) diff --git a/tests/backends/base/library.py b/tests/backends/base/library.py index 50b73040..4e9232e5 100644 --- a/tests/backends/base/library.py +++ b/tests/backends/base/library.py @@ -43,12 +43,12 @@ class LibraryControllerTest(object): pass def test_lookup(self): - track = self.library.lookup(self.tracks[0].uri) - self.assertEqual(track, self.tracks[0]) + tracks = self.library.lookup(self.tracks[0].uri) + self.assertEqual(tracks, self.tracks[0:1]) def test_lookup_unknown_track(self): - track = self.library.lookup('fake uri') - self.assertEquals(track, None) + tracks = self.library.lookup('fake uri') + self.assertEqual(tracks, []) def test_find_exact_no_hits(self): result = self.library.find_exact(track=['unknown track']) diff --git a/tests/core/library_test.py b/tests/core/library_test.py index 40b928d8..1bd481de 100644 --- a/tests/core/library_test.py +++ b/tests/core/library_test.py @@ -41,10 +41,10 @@ class CoreLibraryTest(unittest.TestCase): self.assertFalse(self.library1.lookup.called) self.library2.lookup.assert_called_once_with('dummy2:a') - def test_lookup_fails_for_dummy3_track(self): + def test_lookup_returns_nothing_for_dummy3_track(self): result = self.core.library.lookup('dummy3:a') - self.assertIsNone(result) + self.assertEqual(result, []) self.assertFalse(self.library1.lookup.called) self.assertFalse(self.library2.lookup.called)