Merge branch 'develop' into feature/multi-backend

Conflicts:
	mopidy/backends/local/__init__.py
This commit is contained in:
Stein Magnus Jodal 2010-11-02 00:33:06 +01:00
commit 0b681a4e4c
28 changed files with 186 additions and 146 deletions

0
bin/mopidy Normal file → Executable file
View File

View File

@ -17,15 +17,15 @@ if __name__ == '__main__':
def debug(uri, error):
print >> sys.stderr, 'Failed %s: %s' % (uri, error)
print >> sys.stderr, 'Scanning %s' % settings.LOCAL_MUSIC_FOLDER
print >> sys.stderr, 'Scanning %s' % settings.LOCAL_MUSIC_PATH
scanner = Scanner(settings.LOCAL_MUSIC_FOLDER, store, debug)
scanner = Scanner(settings.LOCAL_MUSIC_PATH, store, debug)
scanner.start()
print >> sys.stderr, 'Done'
for a in tracks_to_tag_cache_format(tracks):
if len(a) == 1:
print a[0]
print (u'%s' % a).encode('utf-8')
else:
print u': '.join([unicode(b) for b in a]).encode('utf-8')
print (u'%s: %s' % a).encode('utf-8')

View File

@ -1,6 +1,6 @@
***********************
:mod:`mopidy.frontends`
***********************
************
Frontend API
************
A frontend may do whatever it wants to, including creating threads, opening TCP
ports and exposing Mopidy for a type of clients.
@ -9,14 +9,6 @@ Frontends got one main limitation: they are restricted to passing messages
through the ``core_queue`` for all communication with the rest of Mopidy. Thus,
the frontend API is very small and reveals little of what a frontend may do.
.. automodule:: mopidy.frontends
:synopsis: Frontend API
:members:
Frontend API
============
.. warning::
A stable frontend API is not available yet, as we've only implemented a

View File

@ -1,6 +1,6 @@
********************
:mod:`mopidy.mixers`
********************
*********
Mixer API
*********
Mixers are responsible for controlling volume. Clients of the mixers will
simply instantiate a mixer and read/write to the ``volume`` attribute::
@ -24,10 +24,6 @@ enable one of the hardware device mixers, you must the set
:attr:`mopidy.settings.MIXER` setting to point to one of the classes found
below, and possibly add some extra settings required by the mixer you choose.
Mixer API
=========
All mixers should subclass :class:`mopidy.mixers.BaseMixer` and override
methods as described below.

View File

@ -1,6 +1,6 @@
********************
:mod:`mopidy.models`
********************
***********
Data models
***********
These immutable data models are used for all data transfer within the Mopidy
backends and between the backends and the MPD frontend. All fields are optional

View File

@ -1,15 +1,17 @@
*********************
:mod:`mopidy.outputs`
*********************
**********
Output API
**********
Outputs are responsible for playing audio.
.. warning::
Output API
==========
A stable output API is not available yet, as we've only implemented a
single output module.
A stable output API is not available yet, as we've only implemented a single
output module.
.. automodule:: mopidy.outputs.base
:synopsis: Base class for outputs
:members:
Output implementations

View File

@ -1,27 +0,0 @@
**********************
:mod:`mopidy.settings`
**********************
Changing settings
=================
For any Mopidy installation you will need to change at least a couple of
settings. To do this, create a new file in the ``~/.mopidy/`` directory
named ``settings.py`` and add settings you need to change from their defaults
there.
A complete ``~/.mopidy/settings.py`` may look like this::
MPD_SERVER_HOSTNAME = u'::'
SPOTIFY_USERNAME = u'alice'
SPOTIFY_PASSWORD = u'mysecret'
Available settings
==================
.. automodule:: mopidy.settings
:synopsis: Available settings and their default values
:members:
:undoc-members:

View File

@ -2,13 +2,31 @@
Settings
********
Mopidy has lots of settings. Luckily, you only need to change a few, and stay
ignorant of the rest. Below you can find guides for typical configuration
changes you may want to do, and a complete listing of available settings.
Changing settings
=================
Mopidy reads settings from the file ``~/.mopidy/settings.py``, where ``~``
means your *home directory*. If your username is ``alice`` and you are running
Linux, the settings file should probably be at
``/home/alice/.mopidy/settings.py``.
You can either create this file yourself, or run the ``mopidy`` command, and it
will create an empty settings file for you.
You can either create the settings file yourself, or run the ``mopidy``
command, and it will create an empty settings file for you.
When you have created the settings file, open it in a text editor, and add
settings you want to change. If you want to keep the default value for setting,
you should *not* redefine it in your own settings file.
A complete ``~/.mopidy/settings.py`` may look as simple as this::
MPD_SERVER_HOSTNAME = u'::'
SPOTIFY_USERNAME = u'alice'
SPOTIFY_PASSWORD = u'mysecret'
Music from Spotify
@ -47,12 +65,12 @@ Generating a tag cache
Previously the local storage backend relied purely on ``tag_cache`` files
generated by the original MPD server. To remedy this the command
:command:`mopidy-scan` has been created. The program will scan your current
:attr:`mopidy.settings.LOCAL_MUSIC_FOLDER` and build a MPD compatible
:attr:`mopidy.settings.LOCAL_MUSIC_PATH` and build a MPD compatible
``tag_cache``.
To make a ``tag_cache`` of your local music available for Mopidy:
#. Ensure that :attr:`mopidy.settings.LOCAL_MUSIC_FOLDER` points to where your
#. Ensure that :attr:`mopidy.settings.LOCAL_MUSIC_PATH` points to where your
music is located. Check the current setting by running::
mopidy --list-settings
@ -64,7 +82,7 @@ To make a ``tag_cache`` of your local music available for Mopidy:
mopidy-scan > tag_cache
#. Move the ``tag_cache`` file to the location
:attr:`mopidy.settings.LOCAL_TAG_CACHE` is set to, or change the setting to
:attr:`mopidy.settings.LOCAL_TAG_CACHE_FILE` is set to, or change the setting to
point to where your ``tag_cache`` file is.
#. Start Mopidy, find the music library in a client, and play some local music!
@ -88,3 +106,12 @@ file::
LASTFM_USERNAME = u'myusername'
LASTFM_PASSWORD = u'mysecret'
Available settings
==================
.. automodule:: mopidy.settings
:synopsis: Available settings and their default values
:members:
:undoc-members:

View File

@ -93,7 +93,7 @@ class DummyStoredPlaylistsProvider(BaseStoredPlaylistsProvider):
def rename(self, playlist, new_name):
self._playlists[self._playlists.index(playlist)] = \
playlist.with_(name=new_name)
playlist.copy(name=new_name)
def save(self, playlist):
self._playlists.append(playlist)

View File

@ -19,7 +19,7 @@ class LibspotifyBackend(BaseBackend):
**Settings:**
- :attr:`mopidy.settings.SPOTIFY_LIB_CACHE`
- :attr:`mopidy.settings.SPOTIFY_CACHE_PATH`
- :attr:`mopidy.settings.SPOTIFY_USERNAME`
- :attr:`mopidy.settings.SPOTIFY_PASSWORD`

View File

@ -15,8 +15,8 @@ logger = logging.getLogger('mopidy.backends.libspotify.session_manager')
# LibspotifySessionManager: Too many ancestors (9/7)
class LibspotifySessionManager(SpotifySessionManager, BaseThread):
cache_location = os.path.expanduser(settings.SPOTIFY_LIB_CACHE)
settings_location = os.path.expanduser(settings.SPOTIFY_LIB_CACHE)
cache_location = settings.SPOTIFY_CACHE_PATH
settings_location = settings.SPOTIFY_CACHE_PATH
appkey_file = os.path.join(os.path.dirname(__file__), 'spotify_appkey.key')
user_agent = 'Mopidy %s' % get_version()

View File

@ -24,9 +24,9 @@ class LocalBackend(BaseBackend):
**Settings:**
- :attr:`mopidy.settings.LOCAL_MUSIC_FOLDER`
- :attr:`mopidy.settings.LOCAL_PLAYLIST_FOLDER`
- :attr:`mopidy.settings.LOCAL_TAG_CACHE`
- :attr:`mopidy.settings.LOCAL_MUSIC_PATH`
- :attr:`mopidy.settings.LOCAL_PLAYLIST_PATH`
- :attr:`mopidy.settings.LOCAL_TAG_CACHE_FILE`
"""
def __init__(self, *args, **kwargs):
@ -79,7 +79,7 @@ class LocalPlaybackProvider(BasePlaybackProvider):
class LocalStoredPlaylistsProvider(BaseStoredPlaylistsProvider):
def __init__(self, *args, **kwargs):
super(LocalStoredPlaylistsProvider, self).__init__(*args, **kwargs)
self._folder = os.path.expanduser(settings.LOCAL_PLAYLIST_FOLDER)
self._folder = settings.LOCAL_PLAYLIST_PATH
self.refresh()
def lookup(self, uri):
@ -129,7 +129,7 @@ class LocalStoredPlaylistsProvider(BaseStoredPlaylistsProvider):
src = os.path.join(self._folder, playlist.name + '.m3u')
dst = os.path.join(self._folder, name + '.m3u')
renamed = playlist.with_(name=name)
renamed = playlist.copy(name=name)
index = self._playlists.index(playlist)
self._playlists[index] = renamed
@ -156,8 +156,8 @@ class LocalLibraryController(BaseLibraryController):
self.refresh()
def refresh(self, uri=None):
tag_cache = os.path.expanduser(settings.LOCAL_TAG_CACHE)
music_folder = os.path.expanduser(settings.LOCAL_MUSIC_FOLDER)
tag_cache = settings.LOCAL_TAG_CACHE_FILE
music_folder = settings.LOCAL_MUSIC_PATH
tracks = parse_mpd_tag_cache(tag_cache, music_folder)

View File

@ -84,7 +84,7 @@ def parse_mpd_tag_cache(tag_cache, music_dir=''):
_convert_mpd_data(current, tracks, music_dir)
current.clear()
current[key.lower()] = value
current[key.lower()] = value.decode('utf-8')
_convert_mpd_data(current, tracks, music_dir)
@ -106,6 +106,7 @@ def _convert_mpd_data(data, tracks, music_dir):
track_kwargs['artists'] = [artist]
album_kwargs['artists'] = [artist]
# FIXME Newer mpd tag caches support albumartist names
if 'album' in data:
album_kwargs['name'] = data['album']
album = Album(**album_kwargs)
@ -114,11 +115,15 @@ def _convert_mpd_data(data, tracks, music_dir):
if 'title' in data:
track_kwargs['name'] = data['title']
# FIXME what if file is uri - generated tag cache needs to allways make
# LOCAL_MUSIC_PATH relative paths or this code must handle uris
if data['file'][0] == '/':
path = data['file'][1:]
else:
path = data['file']
# FIXME newer mpd tag caches provide musicbrainz ids
track_kwargs['uri'] = path_to_uri(music_dir, path)
track_kwargs['length'] = int(data.get('time', 0)) * 1000

View File

@ -6,7 +6,7 @@ from mopidy.utils.path import mtime as get_mtime
from mopidy.frontends.mpd import protocol
from mopidy.utils.path import path_to_uri, uri_to_path, split_path
def track_to_mpd_format(track, position=None, cpid=None, key=False, mtime=False):
def track_to_mpd_format(track, position=None, cpid=None):
"""
Format track for output to MPD client.
@ -41,10 +41,6 @@ def track_to_mpd_format(track, position=None, cpid=None, key=False, mtime=False)
if position is not None and cpid is not None:
result.append(('Pos', position))
result.append(('Id', cpid))
if key and track.uri:
result.insert(0, ('key', os.path.basename(uri_to_path(track.uri))))
if mtime and track.uri:
result.append(('mtime', get_mtime(uri_to_path(track.uri))))
return result
MPD_KEY_ORDER = '''
@ -127,9 +123,11 @@ def tracks_to_tag_cache_format(tracks):
return result
def _add_to_tag_cache(result, folders, files):
music_folder = settings.LOCAL_MUSIC_PATH
regexp = '^' + re.escape(music_folder).rstrip('/') + '/?'
for path, entry in folders.items():
name = os.path.split(path)[1]
music_folder = os.path.expanduser(settings.LOCAL_MUSIC_FOLDER)
mtime = get_mtime(os.path.join(music_folder, path))
result.append(('directory', path))
result.append(('mtime', mtime))
@ -139,8 +137,12 @@ def _add_to_tag_cache(result, folders, files):
result.append(('songList begin',))
for track in files:
track_result = track_to_mpd_format(track, key=True, mtime=True)
track_result = order_mpd_track_info(track_result)
track_result = dict(track_to_mpd_format(track))
path = uri_to_path(track_result['file'])
track_result['mtime'] = get_mtime(path)
track_result['file'] = re.sub(regexp, '', path)
track_result['key'] = os.path.basename(track_result['file'])
track_result = order_mpd_track_info(track_result.items())
result.extend(track_result)
result.append(('songList end',))
@ -150,7 +152,7 @@ def tracks_to_directory_tree(tracks):
path = u''
current = directories
local_folder = os.path.expanduser(settings.LOCAL_MUSIC_FOLDER)
local_folder = settings.LOCAL_MUSIC_PATH
track_path = uri_to_path(track.uri)
track_path = re.sub('^' + re.escape(local_folder), '', track_path)
track_dir = os.path.dirname(track_path)

View File

@ -179,7 +179,7 @@ class Playlist(ImmutableObject):
def mpd_format(self, *args, **kwargs):
return translator.playlist_to_mpd_format(self, *args, **kwargs)
def with_(self, uri=None, name=None, tracks=None, last_modified=None):
def copy(self, uri=None, name=None, tracks=None, last_modified=None):
"""
Create a new playlist object with the given values. The values that are
not given are taken from the object the method is called on.

View File

@ -5,7 +5,6 @@ import pygst
pygst.require('0.10')
import gst
from os.path import abspath
import datetime
import sys
import threading

View File

@ -77,8 +77,8 @@ LASTFM_PASSWORD = u''
#:
#: Default::
#:
#: LOCAL_MUSIC_FOLDER = u'~/music'
LOCAL_MUSIC_FOLDER = u'~/music'
#: LOCAL_MUSIC_PATH = u'~/music'
LOCAL_MUSIC_PATH = u'~/music'
#: Path to playlist folder with m3u files for local music.
#:
@ -86,8 +86,8 @@ LOCAL_MUSIC_FOLDER = u'~/music'
#:
#: Default::
#:
#: LOCAL_PLAYLIST_FOLDER = u'~/.mopidy/playlists'
LOCAL_PLAYLIST_FOLDER = u'~/.mopidy/playlists'
#: LOCAL_PLAYLIST_PATH = u'~/.mopidy/playlists'
LOCAL_PLAYLIST_PATH = u'~/.mopidy/playlists'
#: Path to tag cache for local music.
#:
@ -95,8 +95,8 @@ LOCAL_PLAYLIST_FOLDER = u'~/.mopidy/playlists'
#:
#: Default::
#:
#: LOCAL_TAG_CACHE = u'~/.mopidy/tag_cache'
LOCAL_TAG_CACHE = u'~/.mopidy/tag_cache'
#: LOCAL_TAG_CACHE_FILE = u'~/.mopidy/tag_cache'
LOCAL_TAG_CACHE_FILE = u'~/.mopidy/tag_cache'
#: Sound mixer to use. See :mod:`mopidy.mixers` for all available mixers.
#:
@ -172,7 +172,7 @@ MPD_SERVER_PORT = 6600
#: Path to the libspotify cache.
#:
#: Used by :mod:`mopidy.backends.libspotify`.
SPOTIFY_LIB_CACHE = u'~/.mopidy/libspotify_cache'
SPOTIFY_CACHE_PATH = u'~/.mopidy/libspotify_cache'
#: Your Spotify Premium username.
#:

View File

@ -22,7 +22,6 @@ def get_or_create_file(filename):
def path_to_uri(*paths):
path = os.path.join(*paths)
#path = os.path.expanduser(path) # FIXME Waiting for test case?
path = path.encode('utf-8')
if sys.platform == 'win32':
return 'file:' + urllib.pathname2url(path)
@ -46,16 +45,13 @@ def split_path(path):
return parts
def find_files(path):
path = os.path.expanduser(path)
if os.path.isfile(path):
filename = os.path.abspath(path)
if not isinstance(filename, unicode):
filename = filename.decode('utf-8')
yield filename
if not isinstance(path, unicode):
path = path.decode('utf-8')
yield path
else:
for dirpath, dirnames, filenames in os.walk(path):
for filename in filenames:
dirpath = os.path.abspath(dirpath)
filename = os.path.join(dirpath, filename)
if not isinstance(filename, unicode):
filename = filename.decode('utf-8')

View File

@ -51,6 +51,9 @@ class SettingsProxy(object):
value = self.current[attr]
if type(value) != bool and not value:
raise SettingsError(u'Setting "%s" is empty.' % attr)
if attr.endswith('_PATH') or attr.endswith('_FILE'):
value = os.path.expanduser(value)
value = os.path.abspath(value)
return value
def __setattr__(self, attr, value):
@ -94,10 +97,14 @@ def validate_settings(defaults, settings):
'DUMP_LOG_FILENAME': 'DEBUG_LOG_FILENAME',
'DUMP_LOG_FORMAT': 'DEBUG_LOG_FORMAT',
'FRONTEND': 'FRONTENDS',
'LOCAL_MUSIC_FOLDER': 'LOCAL_MUSIC_PATH',
'LOCAL_PLAYLIST_FOLDER': 'LOCAL_PLAYLIST_PATH',
'LOCAL_TAG_CACHE': 'LOCAL_TAG_CACHE_FILE',
'SERVER': None,
'SERVER_HOSTNAME': 'MPD_SERVER_HOSTNAME',
'SERVER_PORT': 'MPD_SERVER_PORT',
'SPOTIFY_LIB_APPKEY': None,
'SPOTIFY_LIB_CACHE': 'SPOTIFY_CACHE_PATH',
}
for setting, value in settings.iteritems():

View File

@ -10,9 +10,9 @@ from tests import SkipTest, data_folder
class BaseStoredPlaylistsControllerTest(object):
def setUp(self):
settings.LOCAL_PLAYLIST_FOLDER = tempfile.mkdtemp()
settings.LOCAL_TAG_CACHE = data_folder('library_tag_cache')
settings.LOCAL_MUSIC_FOLDER = data_folder('')
settings.LOCAL_PLAYLIST_PATH = tempfile.mkdtemp()
settings.LOCAL_TAG_CACHE_FILE = data_folder('library_tag_cache')
settings.LOCAL_MUSIC_PATH = data_folder('')
self.backend = self.backend_class(mixer_class=DummyMixer)
self.stored = self.backend.stored_playlists
@ -20,8 +20,8 @@ class BaseStoredPlaylistsControllerTest(object):
def tearDown(self):
self.backend.destroy()
if os.path.exists(settings.LOCAL_PLAYLIST_FOLDER):
shutil.rmtree(settings.LOCAL_PLAYLIST_FOLDER)
if os.path.exists(settings.LOCAL_PLAYLIST_PATH):
shutil.rmtree(settings.LOCAL_PLAYLIST_PATH)
settings.runtime.clear()

View File

@ -17,8 +17,8 @@ class LocalLibraryControllerTest(BaseLibraryControllerTest, unittest.TestCase):
backend_class = LocalBackend
def setUp(self):
settings.LOCAL_TAG_CACHE = data_folder('library_tag_cache')
settings.LOCAL_MUSIC_FOLDER = data_folder('')
settings.LOCAL_TAG_CACHE_FILE = data_folder('library_tag_cache')
settings.LOCAL_MUSIC_PATH = data_folder('')
super(LocalLibraryControllerTest, self).setUp()

View File

@ -25,13 +25,13 @@ class LocalStoredPlaylistsControllerTest(BaseStoredPlaylistsControllerTest,
backend_class = LocalBackend
def test_created_playlist_is_persisted(self):
path = os.path.join(settings.LOCAL_PLAYLIST_FOLDER, 'test.m3u')
path = os.path.join(settings.LOCAL_PLAYLIST_PATH, 'test.m3u')
self.assert_(not os.path.exists(path))
self.stored.create('test')
self.assert_(os.path.exists(path))
def test_saved_playlist_is_persisted(self):
path = os.path.join(settings.LOCAL_PLAYLIST_FOLDER, 'test2.m3u')
path = os.path.join(settings.LOCAL_PLAYLIST_PATH, 'test2.m3u')
self.assert_(not os.path.exists(path))
self.stored.save(Playlist(name='test2'))
self.assert_(os.path.exists(path))
@ -39,13 +39,13 @@ class LocalStoredPlaylistsControllerTest(BaseStoredPlaylistsControllerTest,
def test_deleted_playlist_get_removed(self):
playlist = self.stored.create('test')
self.stored.delete(playlist)
path = os.path.join(settings.LOCAL_PLAYLIST_FOLDER, 'test.m3u')
path = os.path.join(settings.LOCAL_PLAYLIST_PATH, 'test.m3u')
self.assert_(not os.path.exists(path))
def test_renamed_playlist_gets_moved(self):
playlist = self.stored.create('test')
file1 = os.path.join(settings.LOCAL_PLAYLIST_FOLDER, 'test.m3u')
file2 = os.path.join(settings.LOCAL_PLAYLIST_FOLDER, 'test2.m3u')
file1 = os.path.join(settings.LOCAL_PLAYLIST_PATH, 'test.m3u')
file2 = os.path.join(settings.LOCAL_PLAYLIST_PATH, 'test2.m3u')
self.assert_(not os.path.exists(file2))
self.stored.rename(playlist, 'test2')
self.assert_(not os.path.exists(file1))
@ -55,7 +55,7 @@ class LocalStoredPlaylistsControllerTest(BaseStoredPlaylistsControllerTest,
track = Track(uri=generate_song(1))
uri = track.uri[len('file://'):]
playlist = Playlist(tracks=[track], name='test')
path = os.path.join(settings.LOCAL_PLAYLIST_FOLDER, 'test.m3u')
path = os.path.join(settings.LOCAL_PLAYLIST_PATH, 'test.m3u')
self.stored.save(playlist)

View File

@ -116,7 +116,16 @@ class MPDTagCacheToTracksTest(unittest.TestCase):
self.assertEqual(set(expected_tracks), tracks)
def test_unicode_cache(self):
raise SkipTest
tracks = parse_mpd_tag_cache(data_folder('utf8_tag_cache'),
data_folder(''))
uri = path_to_uri(data_folder('song1.mp3'))
artists = [Artist(name=u'æøå')]
album = Album(name=u'æøå', artists=artists)
track = Track(uri=uri, name=u'æøå', artists=artists,
album=album, length=4000)
self.assertEqual(track, list(tracks)[0])
def test_misencoded_cache(self):
# FIXME not sure if this can happen

13
tests/data/utf8_tag_cache Normal file
View File

@ -0,0 +1,13 @@
info_begin
mpd_version: 0.14.2
fs_charset: UTF-8
info_end
songList begin
key: song1.mp3
file: /song1.mp3
Time: 4
Artist: æøå
Title: æøå
Album: æøå
mtime: 1272319626
songList end

View File

@ -3,7 +3,7 @@ import os
import unittest
from mopidy import settings
from mopidy.utils.path import mtime
from mopidy.utils.path import mtime, uri_to_path
from mopidy.frontends.mpd import translator, protocol
from mopidy.models import Album, Artist, Playlist, Track
@ -11,7 +11,7 @@ from tests import data_folder, SkipTest
class TrackMpdFormatTest(unittest.TestCase):
def setUp(self):
settings.LOCAL_MUSIC_FOLDER = '/dir/subdir'
settings.LOCAL_MUSIC_PATH = '/dir/subdir'
mtime.set_fake_time(1234567)
def tearDown(self):
@ -42,21 +42,6 @@ class TrackMpdFormatTest(unittest.TestCase):
self.assert_(('Pos', 1) in result)
self.assert_(('Id', 2) in result)
def test_track_to_mpd_format_with_key(self):
track = Track(uri='file:///dir/subdir/file.mp3')
result = translator.track_to_mpd_format(track, key=True)
self.assert_(('key', 'file.mp3') in result)
def test_track_to_mpd_format_with_key_not_uri_encoded(self):
track = Track(uri='file:///dir/subdir/file%20test.mp3')
result = translator.track_to_mpd_format(track, key=True)
self.assert_(('key', 'file test.mp3') in result)
def test_track_to_mpd_format_with_mtime(self):
uri = translator.path_to_uri(data_folder('blank.mp3'))
result = translator.track_to_mpd_format(Track(uri=uri), mtime=True)
self.assert_(('mtime', 1234567) in result)
def test_track_to_mpd_format_for_nonempty_track(self):
track = Track(
uri=u'a uri',
@ -104,7 +89,7 @@ class PlaylistMpdFormatTest(unittest.TestCase):
class TracksToTagCacheFormatTest(unittest.TestCase):
def setUp(self):
settings.LOCAL_MUSIC_FOLDER = '/dir/subdir'
settings.LOCAL_MUSIC_PATH = '/dir/subdir'
mtime.set_fake_time(1234567)
def tearDown(self):
@ -112,8 +97,13 @@ class TracksToTagCacheFormatTest(unittest.TestCase):
mtime.undo_fake()
def translate(self, track):
result = translator.track_to_mpd_format(track, key=True, mtime=True)
return translator.order_mpd_track_info(result)
folder = settings.LOCAL_MUSIC_PATH
result = dict(translator.track_to_mpd_format(track))
result['file'] = uri_to_path(result['file'])
result['file'] = result['file'][len(folder)+1:]
result['key'] = os.path.basename(result['file'])
result['mtime'] = mtime('')
return translator.order_mpd_track_info(result.items())
def consume_headers(self, result):
self.assertEqual(('info_begin',), result[0])
@ -279,7 +269,7 @@ class TracksToTagCacheFormatTest(unittest.TestCase):
class TracksToDirectoryTreeTest(unittest.TestCase):
def setUp(self):
settings.LOCAL_MUSIC_FOLDER = '/root/'
settings.LOCAL_MUSIC_PATH = '/root/'
def tearDown(self):
settings.runtime.clear()

View File

@ -398,7 +398,7 @@ class PlaylistTest(unittest.TestCase):
last_modified = dt.datetime.now()
playlist = Playlist(uri=u'an uri', name=u'a name', tracks=tracks,
last_modified=last_modified)
new_playlist = playlist.with_(uri=u'another uri')
new_playlist = playlist.copy(uri=u'another uri')
self.assertEqual(new_playlist.uri, u'another uri')
self.assertEqual(new_playlist.name, u'a name')
self.assertEqual(new_playlist.tracks, tracks)
@ -409,7 +409,7 @@ class PlaylistTest(unittest.TestCase):
last_modified = dt.datetime.now()
playlist = Playlist(uri=u'an uri', name=u'a name', tracks=tracks,
last_modified=last_modified)
new_playlist = playlist.with_(name=u'another name')
new_playlist = playlist.copy(name=u'another name')
self.assertEqual(new_playlist.uri, u'an uri')
self.assertEqual(new_playlist.name, u'another name')
self.assertEqual(new_playlist.tracks, tracks)
@ -421,7 +421,7 @@ class PlaylistTest(unittest.TestCase):
playlist = Playlist(uri=u'an uri', name=u'a name', tracks=tracks,
last_modified=last_modified)
new_tracks = [Track(), Track()]
new_playlist = playlist.with_(tracks=new_tracks)
new_playlist = playlist.copy(tracks=new_tracks)
self.assertEqual(new_playlist.uri, u'an uri')
self.assertEqual(new_playlist.name, u'a name')
self.assertEqual(new_playlist.tracks, new_tracks)
@ -433,7 +433,7 @@ class PlaylistTest(unittest.TestCase):
new_last_modified = last_modified + dt.timedelta(1)
playlist = Playlist(uri=u'an uri', name=u'a name', tracks=tracks,
last_modified=last_modified)
new_playlist = playlist.with_(last_modified=new_last_modified)
new_playlist = playlist.copy(last_modified=new_last_modified)
self.assertEqual(new_playlist.uri, u'an uri')
self.assertEqual(new_playlist.name, u'a name')
self.assertEqual(new_playlist.tracks, tracks)

View File

@ -34,9 +34,6 @@ class GetOrCreateFolderTest(unittest.TestCase):
self.assert_(os.path.isdir(self.parent))
self.assertEqual(created, self.parent)
def test_that_userfolder_is_expanded(self):
raise SkipTest # Not sure how to safely test this
class PathToFileURITest(unittest.TestCase):
def test_simple_path(self):
@ -139,9 +136,6 @@ class FindFilesTest(unittest.TestCase):
self.assert_(is_unicode(name),
'%s is not unicode object' % repr(name))
def test_expanduser(self):
raise SkipTest
class MtimeTest(unittest.TestCase):
def tearDown(self):

View File

@ -1,3 +1,4 @@
import os
import unittest
from mopidy import settings as default_settings_module
@ -65,3 +66,37 @@ class SettingsProxyTest(unittest.TestCase):
def test_runtime_value_included_in_current(self):
self.settings.TEST = 'test'
self.assertEqual(self.settings.current['TEST'], 'test')
def test_value_ending_in_path_is_expanded(self):
self.settings.TEST_PATH = '~/test'
acctual = self.settings.TEST_PATH
expected = os.path.expanduser('~/test')
self.assertEqual(acctual, expected)
def test_value_ending_in_path_is_absolute(self):
self.settings.TEST_PATH = './test'
acctual = self.settings.TEST_PATH
expected = os.path.abspath('./test')
self.assertEqual(acctual, expected)
def test_value_ending_in_file_is_expanded(self):
self.settings.TEST_FILE = '~/test'
acctual = self.settings.TEST_FILE
expected = os.path.expanduser('~/test')
self.assertEqual(acctual, expected)
def test_value_ending_in_file_is_absolute(self):
self.settings.TEST_FILE = './test'
acctual = self.settings.TEST_FILE
expected = os.path.abspath('./test')
self.assertEqual(acctual, expected)
def test_value_not_ending_in_path_or_file_is_not_expanded(self):
self.settings.TEST = '~/test'
acctual = self.settings.TEST
self.assertEqual(acctual, '~/test')
def test_value_not_ending_in_path_or_file_is_not_absolute(self):
self.settings.TEST = './test'
acctual = self.settings.TEST
self.assertEqual(acctual, './test')