Merge branch 'develop' into feature/stored-playlists-cleanup
This commit is contained in:
commit
938524e67e
@ -17,3 +17,5 @@ notifications:
|
||||
- "irc.freenode.org#mopidy"
|
||||
on_success: change
|
||||
on_failure: change
|
||||
use_notice: true
|
||||
skip_join: true
|
||||
|
||||
@ -86,6 +86,16 @@ backends:
|
||||
|
||||
- The Spotify backend now includes release year and artist on albums.
|
||||
|
||||
- Added support for search by filename to local backend.
|
||||
|
||||
**Bug fixes**
|
||||
|
||||
- :issue:`218`: The MPD commands ``listplaylist`` and ``listplaylistinfo`` now
|
||||
accepts unquotes playlist names if they don't contain spaces.
|
||||
|
||||
- The MPD command ``plchanges`` always returned the entire playlist. It now
|
||||
returns an empty response when the client has seen the latest version.
|
||||
|
||||
|
||||
v0.8.1 (2012-10-30)
|
||||
===================
|
||||
|
||||
@ -70,6 +70,8 @@ class BaseLibraryProvider(object):
|
||||
|
||||
class BasePlaybackProvider(object):
|
||||
"""
|
||||
:param audio: the audio actor
|
||||
:type audio: actor proxy to an instance of :class:`mopidy.audio.Audio`
|
||||
:param backend: the backend
|
||||
:type backend: :class:`mopidy.backends.base.Backend`
|
||||
"""
|
||||
|
||||
@ -59,7 +59,7 @@ class LocalLibraryProvider(base.BaseLibraryProvider):
|
||||
result_tracks = filter(album_filter, result_tracks)
|
||||
elif field == 'artist':
|
||||
result_tracks = filter(artist_filter, result_tracks)
|
||||
elif field == 'uri':
|
||||
elif field in ('uri', 'filename'):
|
||||
result_tracks = filter(uri_filter, result_tracks)
|
||||
elif field == 'any':
|
||||
result_tracks = filter(any_filter, result_tracks)
|
||||
@ -93,7 +93,7 @@ class LocalLibraryProvider(base.BaseLibraryProvider):
|
||||
result_tracks = filter(album_filter, result_tracks)
|
||||
elif field == 'artist':
|
||||
result_tracks = filter(artist_filter, result_tracks)
|
||||
elif field == 'uri':
|
||||
elif field in ('uri', 'filename'):
|
||||
result_tracks = filter(uri_filter, result_tracks)
|
||||
elif field == 'any':
|
||||
result_tracks = filter(any_filter, result_tracks)
|
||||
|
||||
@ -307,7 +307,7 @@ def plchanges(context, version):
|
||||
- Calls ``plchanges "-1"`` two times per second to get the entire playlist.
|
||||
"""
|
||||
# XXX Naive implementation that returns all tracks as changed
|
||||
if int(version) < context.core.current_playlist.version:
|
||||
if int(version) < context.core.current_playlist.version.get():
|
||||
return translator.tracks_to_mpd_format(
|
||||
context.core.current_playlist.cp_tracks.get())
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ from mopidy.frontends.mpd.protocol import handle_request
|
||||
from mopidy.frontends.mpd.translator import playlist_to_mpd_format
|
||||
|
||||
|
||||
@handle_request(r'^listplaylist (?P<name>\S+)$')
|
||||
@handle_request(r'^listplaylist "(?P<name>[^"]+)"$')
|
||||
def listplaylist(context, name):
|
||||
"""
|
||||
@ -27,6 +28,7 @@ def listplaylist(context, name):
|
||||
raise MpdNoExistError(u'No such playlist', command=u'listplaylist')
|
||||
|
||||
|
||||
@handle_request(r'^listplaylistinfo (?P<name>\S+)$')
|
||||
@handle_request(r'^listplaylistinfo "(?P<name>[^"]+)"$')
|
||||
def listplaylistinfo(context, name):
|
||||
"""
|
||||
|
||||
@ -25,17 +25,14 @@ class MpdSession(network.LineProtocol):
|
||||
self.send_lines([u'OK MPD %s' % protocol.VERSION])
|
||||
|
||||
def on_line_received(self, line):
|
||||
logger.debug(
|
||||
u'Request from [%s]:%s to %s: %s',
|
||||
self.host, self.port, self.actor_urn, line)
|
||||
logger.debug(u'Request from [%s]:%s: %s', self.host, self.port, line)
|
||||
|
||||
response = self.dispatcher.handle_request(line)
|
||||
if not response:
|
||||
return
|
||||
|
||||
logger.debug(
|
||||
u'Response to [%s]:%s from %s: %s',
|
||||
self.host, self.port, self.actor_urn,
|
||||
u'Response to [%s]:%s: %s', self.host, self.port,
|
||||
formatting.indent(self.terminator.join(response)))
|
||||
|
||||
self.send_lines(response)
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
coverage
|
||||
flake8
|
||||
mock >= 0.7
|
||||
nose
|
||||
pylint
|
||||
tox
|
||||
unittest2
|
||||
yappi
|
||||
|
||||
@ -79,6 +79,15 @@ class LibraryControllerTest(object):
|
||||
result = self.library.find_exact(album=['album2'])
|
||||
self.assertEqual(result, Playlist(tracks=self.tracks[1:2]))
|
||||
|
||||
def test_find_exact_filename(self):
|
||||
track_1_filename = 'file://' + path_to_data_dir('uri1')
|
||||
result = self.library.find_exact(filename=track_1_filename)
|
||||
self.assertEqual(result, Playlist(tracks=self.tracks[:1]))
|
||||
|
||||
track_2_filename = 'file://' + path_to_data_dir('uri2')
|
||||
result = self.library.find_exact(filename=track_2_filename)
|
||||
self.assertEqual(result, Playlist(tracks=self.tracks[1:2]))
|
||||
|
||||
def test_find_exact_wrong_type(self):
|
||||
test = lambda: self.library.find_exact(wrong=['test'])
|
||||
self.assertRaises(LookupError, test)
|
||||
@ -137,6 +146,13 @@ class LibraryControllerTest(object):
|
||||
result = self.library.search(uri=['RI2'])
|
||||
self.assertEqual(result, Playlist(tracks=self.tracks[1:2]))
|
||||
|
||||
def test_search_filename(self):
|
||||
result = self.library.search(filename=['RI1'])
|
||||
self.assertEqual(result, Playlist(tracks=self.tracks[:1]))
|
||||
|
||||
result = self.library.search(filename=['RI2'])
|
||||
self.assertEqual(result, Playlist(tracks=self.tracks[1:2]))
|
||||
|
||||
def test_search_any(self):
|
||||
result = self.library.search(any=['Tist1'])
|
||||
self.assertEqual(result, Playlist(tracks=self.tracks[:1]))
|
||||
|
||||
@ -364,7 +364,7 @@ class CurrentPlaylistHandlerTest(protocol.BaseTestCase):
|
||||
self.sendRequest(u'playlistsearch any "needle"')
|
||||
self.assertEqualResponse(u'ACK [0@0] {} Not implemented')
|
||||
|
||||
def test_plchanges(self):
|
||||
def test_plchanges_with_lower_version_returns_changes(self):
|
||||
self.core.current_playlist.append(
|
||||
[Track(name='a'), Track(name='b'), Track(name='c')])
|
||||
|
||||
@ -374,6 +374,28 @@ class CurrentPlaylistHandlerTest(protocol.BaseTestCase):
|
||||
self.assertInResponse(u'Title: c')
|
||||
self.assertInResponse(u'OK')
|
||||
|
||||
def test_plchanges_with_equal_version_returns_nothing(self):
|
||||
self.core.current_playlist.append(
|
||||
[Track(name='a'), Track(name='b'), Track(name='c')])
|
||||
|
||||
self.assertEqual(self.core.current_playlist.version.get(), 1)
|
||||
self.sendRequest(u'plchanges "1"')
|
||||
self.assertNotInResponse(u'Title: a')
|
||||
self.assertNotInResponse(u'Title: b')
|
||||
self.assertNotInResponse(u'Title: c')
|
||||
self.assertInResponse(u'OK')
|
||||
|
||||
def test_plchanges_with_greater_version_returns_nothing(self):
|
||||
self.core.current_playlist.append(
|
||||
[Track(name='a'), Track(name='b'), Track(name='c')])
|
||||
|
||||
self.assertEqual(self.core.current_playlist.version.get(), 1)
|
||||
self.sendRequest(u'plchanges "2"')
|
||||
self.assertNotInResponse(u'Title: a')
|
||||
self.assertNotInResponse(u'Title: b')
|
||||
self.assertNotInResponse(u'Title: c')
|
||||
self.assertInResponse(u'OK')
|
||||
|
||||
def test_plchanges_with_minus_one_returns_entire_playlist(self):
|
||||
self.core.current_playlist.append(
|
||||
[Track(name='a'), Track(name='b'), Track(name='c')])
|
||||
|
||||
@ -14,6 +14,14 @@ class StoredPlaylistsHandlerTest(protocol.BaseTestCase):
|
||||
self.assertInResponse(u'file: file:///dev/urandom')
|
||||
self.assertInResponse(u'OK')
|
||||
|
||||
def test_listplaylist_without_quotes(self):
|
||||
self.core.stored_playlists.playlists = [
|
||||
Playlist(name='name', tracks=[Track(uri='file:///dev/urandom')])]
|
||||
|
||||
self.sendRequest(u'listplaylist name')
|
||||
self.assertInResponse(u'file: file:///dev/urandom')
|
||||
self.assertInResponse(u'OK')
|
||||
|
||||
def test_listplaylist_fails_if_no_playlist_is_found(self):
|
||||
self.sendRequest(u'listplaylist "name"')
|
||||
self.assertEqualResponse(u'ACK [50@0] {listplaylist} No such playlist')
|
||||
@ -28,6 +36,16 @@ class StoredPlaylistsHandlerTest(protocol.BaseTestCase):
|
||||
self.assertNotInResponse(u'Pos: 0')
|
||||
self.assertInResponse(u'OK')
|
||||
|
||||
def test_listplaylistinfo_without_quotes(self):
|
||||
self.core.stored_playlists.playlists = [
|
||||
Playlist(name='name', tracks=[Track(uri='file:///dev/urandom')])]
|
||||
|
||||
self.sendRequest(u'listplaylistinfo name')
|
||||
self.assertInResponse(u'file: file:///dev/urandom')
|
||||
self.assertInResponse(u'Track: 0')
|
||||
self.assertNotInResponse(u'Pos: 0')
|
||||
self.assertInResponse(u'OK')
|
||||
|
||||
def test_listplaylistinfo_fails_if_no_playlist_is_found(self):
|
||||
self.sendRequest(u'listplaylistinfo "name"')
|
||||
self.assertEqualResponse(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user