diff --git a/docs/api/backends.rst b/docs/api/backends.rst index de1957e8..617bcb94 100644 --- a/docs/api/backends.rst +++ b/docs/api/backends.rst @@ -116,8 +116,16 @@ Playback provider :undoc-members: -Backend implementations -======================= +Stored playlists provider +------------------------- + +.. autoclass:: mopidy.backends.base.BaseStoredPlaylistsProvider + :members: + :undoc-members: + + +Backend provider implementations +================================ * :mod:`mopidy.backends.dummy` * :mod:`mopidy.backends.libspotify` diff --git a/mopidy/backends/base/__init__.py b/mopidy/backends/base/__init__.py index eb75467c..7ee86015 100644 --- a/mopidy/backends/base/__init__.py +++ b/mopidy/backends/base/__init__.py @@ -4,15 +4,16 @@ import random import time from mopidy import settings -from mopidy.backends.base.current_playlist import BaseCurrentPlaylistController -from mopidy.backends.base.library import BaseLibraryController -from mopidy.backends.base.playback import (BasePlaybackController, - BasePlaybackProvider) -from mopidy.backends.base.stored_playlists import BaseStoredPlaylistsController from mopidy.frontends.mpd import translator from mopidy.models import Playlist from mopidy.utils import get_class +from .current_playlist import BaseCurrentPlaylistController +from .library import BaseLibraryController +from .playback import BasePlaybackController, BasePlaybackProvider +from .stored_playlists import (BaseStoredPlaylistsController, + BaseStoredPlaylistsProvider) + logger = logging.getLogger('mopidy.backends.base') __all__ = ['BaseBackend', 'BasePlaybackController', 'BasePlaybackProvider', diff --git a/mopidy/backends/base/stored_playlists.py b/mopidy/backends/base/stored_playlists.py index 61722c81..cf14db9d 100644 --- a/mopidy/backends/base/stored_playlists.py +++ b/mopidy/backends/base/stored_playlists.py @@ -7,24 +7,30 @@ class BaseStoredPlaylistsController(object): """ :param backend: backend the controller is a part of :type backend: :class:`BaseBackend` + :param provider: provider the controller should use + :type provider: instance of :class:`BaseStoredPlaylistsProvider` """ - def __init__(self, backend): + def __init__(self, backend, provider): self.backend = backend - self._playlists = [] + self.provider = provider def destroy(self): """Cleanup after component.""" - pass + self.provider.destroy() @property def playlists(self): - """List of :class:`mopidy.models.Playlist`.""" - return copy(self._playlists) + """ + Currently stored playlists. + + Read/write. List of :class:`mopidy.models.Playlist`. + """ + return self.provider.playlists @playlists.setter def playlists(self, playlists): - self._playlists = playlists + self.provider.playlists = playlists def create(self, name): """ @@ -34,7 +40,7 @@ class BaseStoredPlaylistsController(object): :type name: string :rtype: :class:`mopidy.models.Playlist` """ - raise NotImplementedError + return self.provider.create(name) def delete(self, playlist): """ @@ -43,7 +49,7 @@ class BaseStoredPlaylistsController(object): :param playlist: the playlist to delete :type playlist: :class:`mopidy.models.Playlist` """ - raise NotImplementedError + return self.provider.delete(playlist) def get(self, **criteria): """ @@ -55,13 +61,14 @@ class BaseStoredPlaylistsController(object): get(name='a') # Returns track with name 'a' get(uri='xyz') # Returns track with URI 'xyz' - get(name='a', uri='xyz') # Returns track with name 'a' and URI 'xyz' + get(name='a', uri='xyz') # Returns track with name 'a' and URI + # 'xyz' :param criteria: one or more criteria to match by :type criteria: dict :rtype: :class:`mopidy.models.Playlist` """ - matches = self._playlists + matches = self.playlists for (key, value) in criteria.iteritems(): matches = filter(lambda p: getattr(p, key) == value, matches) if len(matches) == 1: @@ -82,11 +89,14 @@ class BaseStoredPlaylistsController(object): :type uri: string :rtype: :class:`mopidy.models.Playlist` """ - raise NotImplementedError + return self.provider.lookup(uri) def refresh(self): - """Refresh stored playlists.""" - raise NotImplementedError + """ + Refresh the stored playlists in + :attr:`mopidy.backends.base.BaseStoredPlaylistsController.playlists`. + """ + return self.provider.refresh(uri) def rename(self, playlist, new_name): """ @@ -97,7 +107,7 @@ class BaseStoredPlaylistsController(object): :param new_name: the new name :type new_name: string """ - raise NotImplementedError + return self.provider.rename(playlist, new_name) def save(self, playlist): """ @@ -106,4 +116,85 @@ class BaseStoredPlaylistsController(object): :param playlist: the playlist :type playlist: :class:`mopidy.models.Playlist` """ + return self.provider.save(playlist) + + +class BaseStoredPlaylistsProvider(object): + """ + :param backend: backend the controller is a part of + :type backend: :class:`BaseBackend` + """ + + def __init__(self, backend): + self.backend = backend + self._playlists = [] + + def destroy(self): + """ + Cleanup after component. + + May be overridden by subclasses. + """ + pass + + @property + def playlists(self): + """ + Currently stored playlists. + + Read/write. List of :class:`mopidy.models.Playlist`. + """ + return copy(self._playlists) + + @playlists.setter + def playlists(self, playlists): + self._playlists = playlists + + def create(self, name): + """ + To be overridden by subclass. + + See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.create`. + """ raise NotImplementedError + + def delete(self, playlist): + """ + To be overridden by subclass. + + See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.delete`. + """ + raise NotImplementedError + + def lookup(self, uri): + """ + To be overridden by subclass. + + See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.lookup`. + """ + raise NotImplementedError + + def refresh(self): + """ + To be overridden by subclass. + + See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.refresh`. + """ + raise NotImplementedError + + def rename(self, playlist, new_name): + """ + To be overridden by subclass. + + See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.rename`. + """ + raise NotImplementedError + + def save(self, playlist): + """ + To be overridden by subclass. + + See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.save`. + """ + raise NotImplementedError + diff --git a/mopidy/backends/dummy/__init__.py b/mopidy/backends/dummy/__init__.py index 7a2788b7..3b94452b 100644 --- a/mopidy/backends/dummy/__init__.py +++ b/mopidy/backends/dummy/__init__.py @@ -1,6 +1,6 @@ from mopidy.backends.base import (BaseBackend, BaseCurrentPlaylistController, BasePlaybackController, BasePlaybackProvider, BaseLibraryController, - BaseStoredPlaylistsController) + BaseStoredPlaylistsController, BaseStoredPlaylistsProvider) from mopidy.models import Playlist class DummyBackend(BaseBackend): @@ -22,7 +22,9 @@ class DummyBackend(BaseBackend): self.playback = DummyPlaybackController(backend=self, provider=playback_provider) - self.stored_playlists = DummyStoredPlaylistsController(backend=self) + stored_playlists_provider = DummyStoredPlaylistsProvider(backend=self) + self.stored_playlists = BaseStoredPlaylistsController(backend=self, + provider=stored_playlists_provider) self.uri_handlers = [u'dummy:'] @@ -75,9 +77,7 @@ class DummyPlaybackProvider(BasePlaybackProvider): return True -class DummyStoredPlaylistsController(BaseStoredPlaylistsController): - _playlists = [] - +class DummyStoredPlaylistsProvider(BaseStoredPlaylistsProvider): def create(self, name): playlist = Playlist(name=name) self._playlists.append(playlist) diff --git a/mopidy/backends/libspotify/__init__.py b/mopidy/backends/libspotify/__init__.py index c067cb67..dbbd4804 100644 --- a/mopidy/backends/libspotify/__init__.py +++ b/mopidy/backends/libspotify/__init__.py @@ -2,7 +2,7 @@ import logging from mopidy import settings from mopidy.backends.base import (BaseBackend, BaseCurrentPlaylistController, - BasePlaybackController) + BasePlaybackController, BaseStoredPlaylistsController) logger = logging.getLogger('mopidy.backends.libspotify') @@ -36,7 +36,7 @@ class LibspotifyBackend(BaseBackend): def __init__(self, *args, **kwargs): from .library import LibspotifyLibraryController from .playback import LibspotifyPlaybackProvider - from .stored_playlists import LibspotifyStoredPlaylistsController + from .stored_playlists import LibspotifyStoredPlaylistsProvider super(LibspotifyBackend, self).__init__(*args, **kwargs) @@ -48,8 +48,10 @@ class LibspotifyBackend(BaseBackend): self.playback = BasePlaybackController(backend=self, provider=playback_provider) - self.stored_playlists = LibspotifyStoredPlaylistsController( + stored_playlists_provider = LibspotifyStoredPlaylistsProvider( backend=self) + self.stored_playlists = BaseStoredPlaylistsController(backend=self, + provider=stored_playlists_provider) self.uri_handlers = [u'spotify:', u'http://open.spotify.com/'] diff --git a/mopidy/backends/libspotify/stored_playlists.py b/mopidy/backends/libspotify/stored_playlists.py index 3339578c..6f2a7aad 100644 --- a/mopidy/backends/libspotify/stored_playlists.py +++ b/mopidy/backends/libspotify/stored_playlists.py @@ -1,6 +1,6 @@ -from mopidy.backends.base import BaseStoredPlaylistsController +from mopidy.backends.base import BaseStoredPlaylistsProvider -class LibspotifyStoredPlaylistsController(BaseStoredPlaylistsController): +class LibspotifyStoredPlaylistsProvider(BaseStoredPlaylistsProvider): def create(self, name): pass # TODO diff --git a/mopidy/backends/local/__init__.py b/mopidy/backends/local/__init__.py index 9796414d..b2c36b72 100644 --- a/mopidy/backends/local/__init__.py +++ b/mopidy/backends/local/__init__.py @@ -8,7 +8,7 @@ from mopidy import settings from mopidy.backends.base import (BaseBackend, BaseCurrentPlaylistController, BaseLibraryController, BasePlaybackController, BasePlaybackProvider, - BaseStoredPlaylistsController) + BaseStoredPlaylistsController, BaseStoredPlaylistsProvider) from mopidy.models import Playlist, Track, Album from mopidy.utils.process import pickle_connection @@ -34,7 +34,9 @@ class LocalBackend(BaseBackend): self.library = LocalLibraryController(backend=self) - self.stored_playlists = LocalStoredPlaylistsController(backend=self) + stored_playlists_provider = LocalStoredPlaylistsProvider(backend=self) + self.stored_playlists = BaseStoredPlaylistsController(backend=self, + provider=stored_playlists_provider) self.current_playlist = BaseCurrentPlaylistController(backend=self) @@ -74,9 +76,9 @@ class LocalPlaybackProvider(BasePlaybackProvider): return self.backend.output.set_state('READY') -class LocalStoredPlaylistsController(BaseStoredPlaylistsController): +class LocalStoredPlaylistsProvider(BaseStoredPlaylistsProvider): def __init__(self, *args, **kwargs): - super(LocalStoredPlaylistsController, self).__init__(*args, **kwargs) + super(LocalStoredPlaylistsProvider, self).__init__(*args, **kwargs) self._folder = os.path.expanduser(settings.LOCAL_PLAYLIST_FOLDER) self.refresh()