diff --git a/mopidy/backends/local/__init__.py b/mopidy/backends/local/__init__.py index d24ab010..dedc868c 100644 --- a/mopidy/backends/local/__init__.py +++ b/mopidy/backends/local/__init__.py @@ -1,9 +1,13 @@ from __future__ import unicode_literals +import logging import os import mopidy from mopidy import config, ext +from mopidy.utils import encoding, path + +logger = logging.getLogger('mopidy.backends.local') class Extension(ext.Extension): @@ -27,7 +31,11 @@ class Extension(ext.Extension): return schema def validate_environment(self): - pass + try: + path.get_or_create_dir(b'$XDG_DATA_DIR/mopidy/local') + except EnvironmentError as error: + error = encoding.locale_decode(error) + logger.warning('Could not create local data dir: %s', error) def get_backend_classes(self): from .actor import LocalBackend diff --git a/mopidy/backends/local/json/actor.py b/mopidy/backends/local/json/actor.py index df9ac447..66a6fbd5 100644 --- a/mopidy/backends/local/json/actor.py +++ b/mopidy/backends/local/json/actor.py @@ -1,13 +1,14 @@ from __future__ import unicode_literals import logging +import os import pykka from mopidy.backends import base -from mopidy.utils import encoding, path +from mopidy.utils import encoding -from .library import LocalJsonLibraryProvider +from . import library logger = logging.getLogger('mopidy.backends.local.json') @@ -17,14 +18,13 @@ class LocalJsonBackend(pykka.ThreadingActor, base.Backend): super(LocalJsonBackend, self).__init__() self.config = config - self.check_dirs_and_files() - self.library = LocalJsonLibraryProvider(backend=self) + self.library = library.LocalJsonLibraryProvider(backend=self) self.uri_schemes = ['local'] - def check_dirs_and_files(self): - try: - path.get_or_create_file(self.config['local-json']['json_file']) - except EnvironmentError as error: - logger.warning( - 'Could not create empty json file: %s', - encoding.locale_decode(error)) + if not os.path.exists(config['local-json']['json_file']): + try: + library.write_library(config['local-json']['json_file'], {}) + logger.info('Created empty local JSON library.') + except EnvironmentError as error: + error = encoding.locale_decode(error) + logger.warning('Could not create local library: %s', error) diff --git a/mopidy/backends/local/json/library.py b/mopidy/backends/local/json/library.py index 6bfef783..33427231 100644 --- a/mopidy/backends/local/json/library.py +++ b/mopidy/backends/local/json/library.py @@ -14,13 +14,31 @@ from mopidy.backends.local import search logger = logging.getLogger('mopidy.backends.local.json') -def _load_tracks(json_file): +def load_library(json_file): try: with gzip.open(json_file, 'rb') as fp: - result = json.load(fp, object_hook=models.model_json_decoder) - except IOError: - return [] - return result.get('tracks', []) + return json.load(fp, object_hook=models.model_json_decoder) + except (IOError, ValueError) as e: + logger.warning('Loading JSON local library failed: %s', e) + return {} + + +def write_library(json_file, data): + data['version'] = mopidy.__version__ + directory, basename = os.path.split(json_file) + + # TODO: cleanup directory/basename.* files. + tmp = tempfile.NamedTemporaryFile( + prefix=basename + '.', dir=directory, delete=False) + + try: + with gzip.GzipFile(fileobj=tmp, mode='wb') as fp: + json.dump(data, fp, cls=models.ModelJSONEncoder, + indent=2, separators=(',', ': ')) + os.rename(tmp.name, json_file) + finally: + if os.path.exists(tmp.name): + os.remove(tmp.name) class LocalJsonLibraryProvider(base.BaseLibraryProvider): @@ -36,7 +54,7 @@ class LocalJsonLibraryProvider(base.BaseLibraryProvider): 'Loading local tracks from %s using %s', self._media_dir, self._json_file) - tracks = _load_tracks(self._json_file) + tracks = load_library(self._json_file).get('tracks', []) uris_to_remove = set(self._uri_mapping) for track in tracks: @@ -75,7 +93,7 @@ class LocalJsonLibraryUpdateProvider(base.BaseLibraryProvider): self._json_file = config['local-json']['json_file'] def load(self): - for track in _load_tracks(self._json_file): + for track in load_library(self._json_file).get('tracks', []): self._tracks[track.uri] = track return self._tracks.values() @@ -87,19 +105,4 @@ class LocalJsonLibraryUpdateProvider(base.BaseLibraryProvider): del self._tracks[uri] def commit(self): - directory, basename = os.path.split(self._json_file) - - # TODO: cleanup directory/basename.* files. - tmp = tempfile.NamedTemporaryFile( - prefix=basename + '.', dir=directory, delete=False) - - try: - with gzip.GzipFile(fileobj=tmp, mode='wb') as fp: - data = {'version': mopidy.__version__, - 'tracks': self._tracks.values()} - json.dump(data, fp, cls=models.ModelJSONEncoder, - indent=2, separators=(',', ': ')) - os.rename(tmp.name, self._json_file) - finally: - if os.path.exists(tmp.name): - os.remove(tmp.name) + write_library(self._json_file, {'tracks': self._tracks.values()})