core: Add playlists.as_list() and playlists.get_items(uri)

This commit is contained in:
Stein Magnus Jodal 2015-03-22 22:51:55 +01:00
parent 55b1eb7383
commit 4f3a0839b3
3 changed files with 102 additions and 16 deletions

View File

@ -77,6 +77,17 @@ v1.0.0 (UNRELEASED)
:meth:`mopidy.core.LibraryController.find_exact` to normalize and warn about
bad queries from clients. (Fixes: :issue:`1067`, PR: :issue:`1073`)
- Add :meth:`mopidy.core.PlaylistsController.as_list`. (Fixes: :issue:`1057`,
PR: :issue:`1075`)
- Add :meth:`mopidy.core.PlaylistsController.get_items`. (Fixes: :issue:`1057`,
PR: :issue:`1075`)
- **Deprecated:** :meth:`mopidy.core.PlaylistsController.get_playlists`. Use
:meth:`~mopidy.core.PlaylistsController.as_list` and
:meth:`~mopidy.core.PlaylistsController.get_items` instead. (Fixes:
:issue:`1057`, PR: :issue:`1075`)
**Backend API**
- Remove default implementation of

View File

@ -16,12 +16,52 @@ class PlaylistsController(object):
self.backends = backends
self.core = core
"""
Get the available playlists.
def as_list(self):
"""
Get a list of the currently available playlists.
Returns a list of :class:`~mopidy.models.Ref` objects referring to the
playlists. In other words, no information about the playlists' content
is given.
:rtype: list of :class:`mopidy.models.Ref`
.. versionadded:: 1.0
"""
futures = [
b.playlists.as_list()
for b in self.backends.with_playlists.values()]
results = pykka.get_all(futures)
return list(itertools.chain(*results))
def get_items(self, uri):
"""
Get the items in a playlist specified by ``uri``.
Returns a list of :class:`~mopidy.models.Ref` objects referring to the
playlist's items.
If a playlist with the given ``uri`` doesn't exist, it returns
:class:`None`.
:rtype: list of :class:`mopidy.models.Ref`, or :class:`None`
.. versionadded:: 1.0
"""
uri_scheme = urlparse.urlparse(uri).scheme
backend = self.backends.with_playlists.get(uri_scheme, None)
if backend:
return backend.playlists.get_items(uri).get()
Returns a list of :class:`mopidy.models.Playlist`.
"""
def get_playlists(self, include_tracks=True):
"""
Get the available playlists.
:rtype: list of :class:`mopidy.models.Playlist`
.. deprecated:: 1.0
Use :meth:`as_list` and :meth:`get_items` instead.
"""
futures = [b.playlists.playlists
for b in self.backends.with_playlists.values()]
results = pykka.get_all(futures)
@ -33,7 +73,7 @@ class PlaylistsController(object):
playlists = deprecated_property(get_playlists)
"""
.. deprecated:: 1.0
Use :meth:`get_playlists` instead.
Use :meth:`as_list` and :meth:`get_items` instead.
"""
def create(self, name, uri_scheme=None):

View File

@ -5,19 +5,37 @@ import unittest
import mock
from mopidy import backend, core
from mopidy.models import Playlist, Track
from mopidy.models import Playlist, Ref, Track
class PlaylistsTest(unittest.TestCase):
def setUp(self): # noqa: N802
self.plr1a = Ref.playlist(name='A', uri='dummy1:pl:a')
self.plr1b = Ref.playlist(name='B', uri='dummy1:pl:b')
self.plr2a = Ref.playlist(name='A', uri='dummy2:pl:a')
self.plr2b = Ref.playlist(name='B', uri='dummy2:pl:b')
self.pl1a = Playlist(name='A', tracks=[Track(uri='dummy1:t:a')])
self.pl1b = Playlist(name='B', tracks=[Track(uri='dummy1:t:b')])
self.pl2a = Playlist(name='A', tracks=[Track(uri='dummy2:t:a')])
self.pl2b = Playlist(name='B', tracks=[Track(uri='dummy2:t:b')])
self.sp1 = mock.Mock(spec=backend.PlaylistsProvider)
self.sp1.as_list.return_value.get.return_value = [
self.plr1a, self.plr1b]
self.sp1.playlists.get.return_value = [self.pl1a, self.pl1b]
self.sp2 = mock.Mock(spec=backend.PlaylistsProvider)
self.sp2.as_list.return_value.get.return_value = [
self.plr2a, self.plr2b]
self.sp2.playlists.get.return_value = [self.pl2a, self.pl2b]
self.backend1 = mock.Mock()
self.backend1.uri_schemes.get.return_value = ['dummy1']
self.sp1 = mock.Mock(spec=backend.PlaylistsProvider)
self.backend1.playlists = self.sp1
self.backend2 = mock.Mock()
self.backend2.uri_schemes.get.return_value = ['dummy2']
self.sp2 = mock.Mock(spec=backend.PlaylistsProvider)
self.backend2.playlists = self.sp2
# A backend without the optional playlists provider
@ -26,17 +44,34 @@ class PlaylistsTest(unittest.TestCase):
self.backend3.has_playlists().get.return_value = False
self.backend3.playlists = None
self.pl1a = Playlist(name='A', tracks=[Track(uri='dummy1:a')])
self.pl1b = Playlist(name='B', tracks=[Track(uri='dummy1:b')])
self.sp1.playlists.get.return_value = [self.pl1a, self.pl1b]
self.pl2a = Playlist(name='A', tracks=[Track(uri='dummy2:a')])
self.pl2b = Playlist(name='B', tracks=[Track(uri='dummy2:b')])
self.sp2.playlists.get.return_value = [self.pl2a, self.pl2b]
self.core = core.Core(mixer=None, backends=[
self.backend3, self.backend1, self.backend2])
def test_as_list_combines_result_from_backends(self):
result = self.core.playlists.as_list()
self.assertIn(self.plr1a, result)
self.assertIn(self.plr1b, result)
self.assertIn(self.plr2a, result)
self.assertIn(self.plr2b, result)
def test_get_items_selects_the_matching_backend(self):
ref = Ref.track()
self.sp2.get_items.return_value.get.return_value = [ref]
result = self.core.playlists.get_items('dummy2:pl:a')
self.assertEqual([ref], result)
self.assertFalse(self.sp1.get_items.called)
self.sp2.get_items.assert_called_once_with('dummy2:pl:a')
def test_get_items_with_unknown_uri_scheme_does_nothing(self):
result = self.core.playlists.get_items('unknown:a')
self.assertIsNone(result)
self.assertFalse(self.sp1.delete.called)
self.assertFalse(self.sp2.delete.called)
def test_get_playlists_combines_result_from_backends(self):
result = self.core.playlists.playlists