From 7f80a188c91cb774a9f6f29a8f3e13d0fd825d59 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Mon, 20 May 2013 23:50:46 +0200 Subject: [PATCH] core: Add library updater. Idea behind this class is to have a clear sub-set of our library API that is only used for updating libraries. This makes it very clear what methods are needed for just libaries and additionally updatable libraries. Next couple of commits will build on this idea taking us closer to plugable local libraries. --- mopidy/backends/base.py | 51 +++++++++++++++++++++++++++++++++++++++++ mopidy/scanner.py | 20 +++++++++------- 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/mopidy/backends/base.py b/mopidy/backends/base.py index c45eb771..9f531450 100644 --- a/mopidy/backends/base.py +++ b/mopidy/backends/base.py @@ -15,6 +15,11 @@ class Backend(object): #: the backend doesn't provide a library. library = None + #: The library update provider. An instance of + #: :class:`~mopidy.backends.base.BaseLibraryUpdateProvider`, or + #: :class:`None` if the backend doesn't provide a library. + updater = None + #: The playback provider. An instance of #: :class:`~mopidy.backends.base.BasePlaybackProvider`, or :class:`None` if #: the backend doesn't provide playback. @@ -35,6 +40,9 @@ class Backend(object): def has_library(self): return self.library is not None + def has_updater(self): + return self.updater is not None + def has_playback(self): return self.playback is not None @@ -53,6 +61,7 @@ class BaseLibraryProvider(object): def __init__(self, backend): self.backend = backend + # TODO: replace with search(query, exact=Ture, ...) def find_exact(self, query=None, uris=None): """ See :meth:`mopidy.core.LibraryController.find_exact`. @@ -86,6 +95,48 @@ class BaseLibraryProvider(object): pass +class BaseLibraryUpdateProvider(object): + """ + :param backend: backend the controller is a part of + :type backend: :class:`mopidy.backends.base.Backend` + """ + + pykka_traversable = True + + def __init__(self, backend): + self.backend = backend + + def load(self): + """Loads the library and returns all tracks in it. + + *MUST be implemented by subclass.* + """ + raise NotImplementedError + + def add(self, track): + """Adds given track to library. + + Overwrites any existing entry with same uri. + + *MUST be implemented by subclass.* + """ + raise NotImplementedError + + def remove(self, uri): + """Removes given track from library. + + *MUST be implemented by subclass.* + """ + raise NotImplementedError + + def commit(self): + """Persist changes to library. + + *MAY be implemented by subclass.* + """ + pass + + class BasePlaybackProvider(object): """ :param audio: the audio actor diff --git a/mopidy/scanner.py b/mopidy/scanner.py index 0cc51d2a..ba8f2ff9 100644 --- a/mopidy/scanner.py +++ b/mopidy/scanner.py @@ -111,15 +111,19 @@ def main(): tmp = tempfile.NamedTemporaryFile( prefix=basename + '.', dir=directory, delete=False) - for row in mpd_translator.tracks_to_tag_cache_format( - tracks.values(), config['local']['media_dir']): - if len(row) == 1: - tmp.write(('%s\n' % row).encode('utf-8')) - else: - tmp.write(('%s: %s\n' % row).encode('utf-8')) + try: + for row in mpd_translator.tracks_to_tag_cache_format( + tracks.values(), config['local']['media_dir']): + if len(row) == 1: + tmp.write(('%s\n' % row).encode('utf-8')) + else: + tmp.write(('%s: %s\n' % row).encode('utf-8')) - os.rename(tmp.name, config['local']['tag_cache_file']) - logging.info('Done writing; overwriting active tag cache.') + logging.info('Done writing; overwriting active tag cache.') + os.rename(tmp.name, config['local']['tag_cache_file']) + finally: + if os.path.exists(tmp.name): + os.remove(tmp.name) def parse_args():