merge master branch
This commit is contained in:
commit
2897f8e5f6
@ -15,6 +15,10 @@ Another great release.
|
||||
- Exit early if not Python >= 2.6, < 3.
|
||||
- Include Sphinx scripts for building docs, pylintrc, tests and test data in
|
||||
the packages created by ``setup.py`` for i.e. PyPI.
|
||||
- Backend API:
|
||||
|
||||
- The ``id`` field of :class:`mopidy.models.Track` has been removed, as it is
|
||||
no longer needed after the CPID refactoring.
|
||||
|
||||
|
||||
0.1.0a3 (2010-08-03)
|
||||
|
||||
@ -9,7 +9,6 @@ from mopidy.backends import (BaseBackend, BaseCurrentPlaylistController,
|
||||
BaseLibraryController, BasePlaybackController,
|
||||
BaseStoredPlaylistsController)
|
||||
from mopidy.models import Artist, Album, Track, Playlist
|
||||
from mopidy.utils import spotify_uri_to_int
|
||||
|
||||
logger = logging.getLogger('mopidy.backends.despotify')
|
||||
|
||||
@ -128,10 +127,6 @@ class DespotifyStoredPlaylistsController(BaseStoredPlaylistsController):
|
||||
|
||||
|
||||
class DespotifyTranslator(object):
|
||||
@classmethod
|
||||
def to_mopidy_id(cls, spotify_uri):
|
||||
return spotify_uri_to_int(spotify_uri)
|
||||
|
||||
@classmethod
|
||||
def to_mopidy_artist(cls, spotify_artist):
|
||||
return Artist(
|
||||
@ -160,7 +155,6 @@ class DespotifyTranslator(object):
|
||||
date=date,
|
||||
length=spotify_track.length,
|
||||
bitrate=320,
|
||||
id=cls.to_mopidy_id(spotify_track.get_uri()),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
|
||||
@ -13,7 +13,6 @@ from mopidy.backends import (BaseBackend, BaseCurrentPlaylistController,
|
||||
BaseLibraryController, BasePlaybackController,
|
||||
BaseStoredPlaylistsController)
|
||||
from mopidy.models import Artist, Album, Track, Playlist
|
||||
from mopidy.utils import spotify_uri_to_int
|
||||
|
||||
import alsaaudio
|
||||
|
||||
@ -39,8 +38,7 @@ class LibspotifyBackend(BaseBackend):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(LibspotifyBackend, self).__init__(*args, **kwargs)
|
||||
self.current_playlist = LibspotifyCurrentPlaylistController(
|
||||
backend=self)
|
||||
self.current_playlist = BaseCurrentPlaylistController(backend=self)
|
||||
self.library = LibspotifyLibraryController(backend=self)
|
||||
self.playback = LibspotifyPlaybackController(backend=self)
|
||||
self.stored_playlists = LibspotifyStoredPlaylistsController(
|
||||
@ -60,15 +58,17 @@ class LibspotifyBackend(BaseBackend):
|
||||
return spotify
|
||||
|
||||
|
||||
class LibspotifyCurrentPlaylistController(BaseCurrentPlaylistController):
|
||||
pass
|
||||
|
||||
|
||||
class LibspotifyLibraryController(BaseLibraryController):
|
||||
def find_exact(self, **query):
|
||||
return self.search(**query)
|
||||
|
||||
def lookup(self, uri):
|
||||
spotify_track = Link.from_string(uri).as_track()
|
||||
return LibspotifyTranslator.to_mopidy_track(spotify_track)
|
||||
|
||||
def refresh(self, uri=None):
|
||||
pass # TODO
|
||||
|
||||
def search(self, **query):
|
||||
spotify_query = []
|
||||
for (field, values) in query.iteritems():
|
||||
@ -85,14 +85,6 @@ class LibspotifyLibraryController(BaseLibraryController):
|
||||
logger.debug(u'In search method, search for: %s' % spotify_query)
|
||||
my_end, other_end = multiprocessing.Pipe()
|
||||
self.backend.spotify.search(spotify_query.encode(ENCODING), other_end)
|
||||
my_end.poll(None)
|
||||
logger.debug(u'In search method, receiving search results')
|
||||
playlist = my_end.recv()
|
||||
logger.debug(u'In search method, done receiving search results')
|
||||
logger.debug(['%s' % t.name for t in playlist.tracks])
|
||||
return playlist
|
||||
|
||||
find_exact = search
|
||||
|
||||
|
||||
class LibspotifyPlaybackController(BasePlaybackController):
|
||||
@ -118,20 +110,38 @@ class LibspotifyPlaybackController(BasePlaybackController):
|
||||
# TODO
|
||||
return False
|
||||
|
||||
def _seek(self, time_position):
|
||||
pass # TODO
|
||||
|
||||
def _stop(self):
|
||||
self.backend.spotify.session.play(0)
|
||||
return True
|
||||
|
||||
|
||||
class LibspotifyStoredPlaylistsController(BaseStoredPlaylistsController):
|
||||
pass
|
||||
def create(self, name):
|
||||
pass # TODO
|
||||
|
||||
def delete(self, playlist):
|
||||
pass # TODO
|
||||
|
||||
def lookup(self, uri):
|
||||
pass # TODO
|
||||
|
||||
def refresh(self):
|
||||
pass # TODO
|
||||
|
||||
def rename(self, playlist, new_name):
|
||||
pass # TODO
|
||||
|
||||
def save(self, playlist):
|
||||
pass # TODO
|
||||
|
||||
def search(self, query):
|
||||
pass # TODO
|
||||
|
||||
|
||||
class LibspotifyTranslator(object):
|
||||
@classmethod
|
||||
def to_mopidy_id(cls, spotify_uri):
|
||||
return spotify_uri_to_int(spotify_uri)
|
||||
|
||||
@classmethod
|
||||
def to_mopidy_artist(cls, spotify_artist):
|
||||
if not spotify_artist.is_loaded():
|
||||
@ -166,7 +176,6 @@ class LibspotifyTranslator(object):
|
||||
date=date,
|
||||
length=spotify_track.duration(),
|
||||
bitrate=320,
|
||||
id=cls.to_mopidy_id(uri),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@ -253,15 +262,25 @@ class LibspotifySessionManager(SpotifySessionManager, threading.Thread):
|
||||
|
||||
def search(self, query, connection):
|
||||
"""Search method used by Mopidy backend"""
|
||||
self.connected.wait()
|
||||
def callback(results, userdata):
|
||||
logger.debug(u'In search callback, translating search results')
|
||||
logger.debug(u'In SessionManager.search().callback(), '
|
||||
'translating search results')
|
||||
logger.debug(results.tracks())
|
||||
# TODO Include results from results.albums(), etc. too
|
||||
playlist = Playlist(tracks=[
|
||||
LibspotifyTranslator.to_mopidy_track(t)
|
||||
for t in results.tracks()])
|
||||
logger.debug(u'In search callback, sending search results')
|
||||
logger.debug(u'In SessionManager.search().callback(), '
|
||||
'sending search results')
|
||||
logger.debug(['%s' % t.name for t in playlist.tracks])
|
||||
connection.send(playlist)
|
||||
logger.debug(u'In SessionManager.search().callback(), '
|
||||
'done sending search results')
|
||||
logger.debug(u'In SessionManager.search(), '
|
||||
'waiting for Spotify connection')
|
||||
self.connected.wait()
|
||||
logger.debug(u'In SessionManager.search(), '
|
||||
'sending search query')
|
||||
self.session.search(query, callback)
|
||||
logger.debug(u'In SessionManager.search(), '
|
||||
'done sending search query')
|
||||
|
||||
@ -103,8 +103,6 @@ class Track(ImmutableObject):
|
||||
:type length: integer
|
||||
:param bitrate: bitrate in kbit/s
|
||||
:type bitrate: integer
|
||||
:param id: track ID (unique and non-changing as long as the process lives)
|
||||
:type id: integer
|
||||
"""
|
||||
|
||||
#: The track URI. Read-only.
|
||||
@ -128,9 +126,6 @@ class Track(ImmutableObject):
|
||||
#: The track's bitrate in kbit/s. Read-only.
|
||||
bitrate = None
|
||||
|
||||
#: The track ID. Read-only.
|
||||
id = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._artists = frozenset(kwargs.pop('artists', []))
|
||||
super(Track, self).__init__(*args, **kwargs)
|
||||
|
||||
@ -58,52 +58,6 @@ def unpickle_connection(pickled_connection):
|
||||
(func, args) = pickle.loads(pickled_connection)
|
||||
return func(*args)
|
||||
|
||||
def spotify_uri_to_int(uri, output_bits=31):
|
||||
"""
|
||||
Stable one-way translation from Spotify URI to 31-bit integer.
|
||||
|
||||
Spotify track URIs has 62^22 possible values, which requires 131 bits of
|
||||
storage. The original MPD server uses 32-bit unsigned integers for track
|
||||
IDs. GMPC seems to think the track ID is a signed integer, thus we use 31
|
||||
output bits.
|
||||
|
||||
In other words, this function throws away 100 bits of information. Since we
|
||||
only use the track IDs to identify a track within a single Mopidy instance,
|
||||
this information loss is acceptable. The chances of getting two different
|
||||
tracks with the same track ID loaded in the same Mopidy instance is still
|
||||
rather slim. 1 to 2,147,483,648 to be exact.
|
||||
|
||||
Normal usage, with data loss::
|
||||
|
||||
>>> spotify_uri_to_int('spotify:track:5KRRcT67VNIZUygEbMoIC1')
|
||||
624351954
|
||||
|
||||
No data loss, may be converted back into a Spotify URI::
|
||||
|
||||
>>> spotify_uri_to_int('spotify:track:5KRRcT67VNIZUygEbMoIC1',
|
||||
... output_bits=131)
|
||||
101411513484007705241035418492696638725L
|
||||
|
||||
:param uri: Spotify URI on the format ``spotify:track:*``
|
||||
:type uri: string
|
||||
:param output_bits: number of bits of information kept in the return value
|
||||
:type output_bits: int
|
||||
:rtype: int
|
||||
"""
|
||||
|
||||
CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
|
||||
BITS_PER_CHAR = 6 # int(math.ceil(math.log(len(CHARS), 2)))
|
||||
|
||||
key = uri.split(':')[-1]
|
||||
full_id = 0
|
||||
for i, char in enumerate(key):
|
||||
full_id ^= CHARS.index(char) << BITS_PER_CHAR * i
|
||||
compressed_id = 0
|
||||
while full_id != 0:
|
||||
compressed_id ^= (full_id & (2 ** output_bits - 1))
|
||||
full_id >>= output_bits
|
||||
return int(compressed_id)
|
||||
|
||||
def parse_m3u(file_path):
|
||||
"""
|
||||
Convert M3U file list of uris
|
||||
@ -219,7 +173,6 @@ def _convert_mpd_data(data, tracks, music_dir):
|
||||
|
||||
track_kwargs['uri'] = path_to_uri(music_dir, path)
|
||||
track_kwargs['length'] = int(data.get('time', 0)) * 1000
|
||||
track_kwargs['id'] = len(tracks)
|
||||
|
||||
track = Track(**track_kwargs)
|
||||
tracks.add(track)
|
||||
|
||||
@ -65,22 +65,13 @@ class BaseCurrentPlaylistControllerTest(object):
|
||||
cp_track = self.controller.cp_tracks[1]
|
||||
self.assertEqual(cp_track, self.controller.get(cpid=cp_track[0]))
|
||||
|
||||
@populate_playlist
|
||||
def test_get_by_id(self):
|
||||
cp_track = self.controller.cp_tracks[1]
|
||||
self.assertEqual(cp_track, self.controller.get(id=cp_track[1].id))
|
||||
|
||||
@populate_playlist
|
||||
def test_get_by_id_raises_error_for_invalid_id(self):
|
||||
self.assertRaises(LookupError, lambda: self.controller.get(id=1337))
|
||||
|
||||
@populate_playlist
|
||||
def test_get_by_uri(self):
|
||||
cp_track = self.controller.cp_tracks[1]
|
||||
self.assertEqual(cp_track, self.controller.get(uri=cp_track[1].uri))
|
||||
|
||||
@populate_playlist
|
||||
def test_get_by_uri_raises_error_for_invalid_id(self):
|
||||
def test_get_by_uri_raises_error_for_invalid_uri(self):
|
||||
test = lambda: self.controller.get(uri='foobar')
|
||||
self.assertRaises(LookupError, test)
|
||||
|
||||
@ -106,28 +97,6 @@ class BaseCurrentPlaylistControllerTest(object):
|
||||
self.controller.load(tracks)
|
||||
self.assertEqual(tracks, self.controller.tracks)
|
||||
|
||||
def test_get_by_id_returns_unique_match(self):
|
||||
track = Track(id=1)
|
||||
self.controller.load([Track(id=13), track, Track(id=17)])
|
||||
self.assertEqual(track, self.controller.get(id=1)[1])
|
||||
|
||||
def test_get_by_id_raises_error_if_multiple_matches(self):
|
||||
track = Track(id=1)
|
||||
self.controller.load([Track(id=13), track, track])
|
||||
try:
|
||||
self.controller.get(id=1)
|
||||
self.fail(u'Should raise LookupError if multiple matches')
|
||||
except LookupError as e:
|
||||
self.assertEqual(u'"id=1" match multiple tracks', e[0])
|
||||
|
||||
def test_get_by_id_raises_error_if_no_match(self):
|
||||
self.controller.playlist = Playlist(tracks=[Track(id=13), Track(id=17)])
|
||||
try:
|
||||
self.controller.get(id=1)
|
||||
self.fail(u'Should raise LookupError if no match')
|
||||
except LookupError as e:
|
||||
self.assertEqual(u'"id=1" match no tracks', e[0])
|
||||
|
||||
def test_get_by_uri_returns_unique_match(self):
|
||||
track = Track(uri='a')
|
||||
self.controller.load([Track(uri='z'), track, Track(uri='y')])
|
||||
@ -152,20 +121,20 @@ class BaseCurrentPlaylistControllerTest(object):
|
||||
self.assertEqual(u'"uri=a" match no tracks', e[0])
|
||||
|
||||
def test_get_by_multiple_criteria_returns_elements_matching_all(self):
|
||||
track1 = Track(id=1, uri='a')
|
||||
track2 = Track(id=1, uri='b')
|
||||
track3 = Track(id=2, uri='b')
|
||||
track1 = Track(uri='a', name='x')
|
||||
track2 = Track(uri='b', name='x')
|
||||
track3 = Track(uri='b', name='y')
|
||||
self.controller.load([track1, track2, track3])
|
||||
self.assertEqual(track1, self.controller.get(id=1, uri='a')[1])
|
||||
self.assertEqual(track2, self.controller.get(id=1, uri='b')[1])
|
||||
self.assertEqual(track3, self.controller.get(id=2, uri='b')[1])
|
||||
self.assertEqual(track1, self.controller.get(uri='a', name='x')[1])
|
||||
self.assertEqual(track2, self.controller.get(uri='b', name='x')[1])
|
||||
self.assertEqual(track3, self.controller.get(uri='b', name='y')[1])
|
||||
|
||||
def test_get_by_criteria_that_is_not_present_in_all_elements(self):
|
||||
track1 = Track(id=1)
|
||||
track1 = Track()
|
||||
track2 = Track(uri='b')
|
||||
track3 = Track(id=2)
|
||||
track3 = Track()
|
||||
self.controller.load([track1, track2, track3])
|
||||
self.assertEqual(track1, self.controller.get(id=1)[1])
|
||||
self.assertEqual(track2, self.controller.get(uri='b')[1])
|
||||
|
||||
@populate_playlist
|
||||
def test_load_replaces_playlist(self):
|
||||
@ -244,18 +213,18 @@ class BaseCurrentPlaylistControllerTest(object):
|
||||
track1 = self.controller.tracks[1]
|
||||
track2 = self.controller.tracks[2]
|
||||
version = self.controller.version
|
||||
self.controller.remove(id=track1.id)
|
||||
self.controller.remove(uri=track1.uri)
|
||||
self.assert_(version < self.controller.version)
|
||||
self.assert_(track1 not in self.controller.tracks)
|
||||
self.assertEqual(track2, self.controller.tracks[1])
|
||||
|
||||
@populate_playlist
|
||||
def test_removing_track_that_does_not_exist(self):
|
||||
test = lambda: self.controller.remove(id=12345)
|
||||
test = lambda: self.controller.remove(uri='/nonexistant')
|
||||
self.assertRaises(LookupError, test)
|
||||
|
||||
def test_removing_from_empty_playlist(self):
|
||||
test = lambda: self.controller.remove(id=12345)
|
||||
test = lambda: self.controller.remove(uri='/nonexistant')
|
||||
self.assertRaises(LookupError, test)
|
||||
|
||||
@populate_playlist
|
||||
@ -1025,7 +994,7 @@ class BaseStoredPlaylistsControllerTest(object):
|
||||
except LookupError as e:
|
||||
self.assertEqual(u'"name=b" match multiple playlists', e[0])
|
||||
|
||||
def test_get_by_id_raises_keyerror_if_no_match(self):
|
||||
def test_get_by_name_raises_keyerror_if_no_match(self):
|
||||
self.stored.playlists = [Playlist(name='a'), Playlist(name='b')]
|
||||
try:
|
||||
self.stored.get(name='c')
|
||||
@ -1080,10 +1049,10 @@ class BaseLibraryControllerTest(object):
|
||||
Album(name='album2', artists=artists[1:2]),
|
||||
Album()]
|
||||
tracks = [Track(name='track1', length=4000, artists=artists[:1],
|
||||
album=albums[0], uri='file://' + data_folder('uri1'), id=0),
|
||||
album=albums[0], uri='file://' + data_folder('uri1')),
|
||||
Track(name='track2', length=4000, artists=artists[1:2],
|
||||
album=albums[1], uri='file://' + data_folder('uri2'), id=1),
|
||||
Track(id=3)]
|
||||
album=albums[1], uri='file://' + data_folder('uri2')),
|
||||
Track()]
|
||||
|
||||
def setUp(self):
|
||||
self.backend = self.backend_class(mixer=DummyMixer())
|
||||
|
||||
@ -15,13 +15,13 @@ uris = [
|
||||
|
||||
class DespotifyCurrentPlaylistControllerTest(
|
||||
BaseCurrentPlaylistControllerTest, unittest.TestCase):
|
||||
tracks = [Track(uri=uri, id=i, length=4464) for i, uri in enumerate(uris)]
|
||||
tracks = [Track(uri=uri, length=4464) for i, uri in enumerate(uris)]
|
||||
backend_class = DespotifyBackend
|
||||
|
||||
|
||||
class DespotifyPlaybackControllerTest(
|
||||
BasePlaybackControllerTest, unittest.TestCase):
|
||||
tracks = [Track(uri=uri, id=i, length=4464) for i, uri in enumerate(uris)]
|
||||
tracks = [Track(uri=uri, length=4464) for i, uri in enumerate(uris)]
|
||||
backend_class = DespotifyBackend
|
||||
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ generate_song = lambda i: path_to_uri(song % i)
|
||||
# FIXME can be switched to generic test
|
||||
class GStreamerCurrentPlaylistControllerTest(BaseCurrentPlaylistControllerTest,
|
||||
unittest.TestCase):
|
||||
tracks = [Track(uri=generate_song(i), id=i, length=4464)
|
||||
tracks = [Track(uri=generate_song(i), length=4464)
|
||||
for i in range(1, 4)]
|
||||
|
||||
backend_class = GStreamerBackend
|
||||
@ -31,7 +31,7 @@ class GStreamerCurrentPlaylistControllerTest(BaseCurrentPlaylistControllerTest,
|
||||
|
||||
class GStreamerPlaybackControllerTest(BasePlaybackControllerTest,
|
||||
unittest.TestCase):
|
||||
tracks = [Track(uri=generate_song(i), id=i, length=4464)
|
||||
tracks = [Track(uri=generate_song(i), length=4464)
|
||||
for i in range(1, 4)]
|
||||
backend_class = GStreamerBackend
|
||||
|
||||
@ -42,7 +42,7 @@ class GStreamerPlaybackControllerTest(BasePlaybackControllerTest,
|
||||
|
||||
def add_track(self, path):
|
||||
uri = path_to_uri(data_folder(path))
|
||||
track = Track(uri=uri, id=1, length=4464)
|
||||
track = Track(uri=uri, length=4464)
|
||||
self.backend.current_playlist.add(track)
|
||||
|
||||
def test_uri_handler(self):
|
||||
|
||||
@ -15,13 +15,13 @@ uris = [
|
||||
|
||||
class LibspotifyCurrentPlaylistControllerTest(
|
||||
BaseCurrentPlaylistControllerTest, unittest.TestCase):
|
||||
tracks = [Track(uri=uri, id=i, length=4464) for i, uri in enumerate(uris)]
|
||||
tracks = [Track(uri=uri, length=4464) for i, uri in enumerate(uris)]
|
||||
backend_class = LibspotifyBackend
|
||||
|
||||
|
||||
class LibspotifyPlaybackControllerTest(
|
||||
BasePlaybackControllerTest, unittest.TestCase):
|
||||
tracks = [Track(uri=uri, id=i, length=4464) for i, uri in enumerate(uris)]
|
||||
tracks = [Track(uri=uri, length=4464) for i, uri in enumerate(uris)]
|
||||
backend_class = LibspotifyBackend
|
||||
|
||||
|
||||
|
||||
@ -222,12 +222,6 @@ class TrackTest(unittest.TestCase):
|
||||
self.assertEqual(track.bitrate, bitrate)
|
||||
self.assertRaises(AttributeError, setattr, track, 'bitrate', None)
|
||||
|
||||
def test_id(self):
|
||||
track_id = 17
|
||||
track = Track(id=track_id)
|
||||
self.assertEqual(track.id, track_id)
|
||||
self.assertRaises(AttributeError, setattr, track, 'id', None)
|
||||
|
||||
def test_invalid_kwarg(self):
|
||||
test = lambda: Track(foo='baz')
|
||||
self.assertRaises(TypeError, test)
|
||||
@ -291,20 +285,14 @@ class TrackTest(unittest.TestCase):
|
||||
self.assertEqual(track1, track2)
|
||||
self.assertEqual(hash(track1), hash(track2))
|
||||
|
||||
def test_eq_id(self):
|
||||
track1 = Track(id=100)
|
||||
track2 = Track(id=100)
|
||||
self.assertEqual(track1, track2)
|
||||
self.assertEqual(hash(track1), hash(track2))
|
||||
|
||||
def test_eq(self):
|
||||
date = dt.date.today()
|
||||
artists = [Artist()]
|
||||
album = Album()
|
||||
track1 = Track(uri=u'uri', name=u'name', artists=artists, album=album,
|
||||
track_no=1, date=date, length=100, bitrate=100, id=2)
|
||||
track_no=1, date=date, length=100, bitrate=100)
|
||||
track2 = Track(uri=u'uri', name=u'name', artists=artists, album=album,
|
||||
track_no=1, date=date, length=100, bitrate=100, id=2)
|
||||
track_no=1, date=date, length=100, bitrate=100)
|
||||
self.assertEqual(track1, track2)
|
||||
self.assertEqual(hash(track1), hash(track2))
|
||||
|
||||
@ -362,20 +350,14 @@ class TrackTest(unittest.TestCase):
|
||||
self.assertNotEqual(track1, track2)
|
||||
self.assertNotEqual(hash(track1), hash(track2))
|
||||
|
||||
def test_ne_id(self):
|
||||
track1 = Track(id=100)
|
||||
track2 = Track(id=200)
|
||||
self.assertNotEqual(track1, track2)
|
||||
self.assertNotEqual(hash(track1), hash(track2))
|
||||
|
||||
def test_ne(self):
|
||||
track1 = Track(uri=u'uri1', name=u'name1',
|
||||
artists=[Artist(name=u'name1')], album=Album(name=u'name1'),
|
||||
track_no=1, date=dt.date.today(), length=100, bitrate=100, id=2)
|
||||
track_no=1, date=dt.date.today(), length=100, bitrate=100)
|
||||
track2 = Track(uri=u'uri2', name=u'name2',
|
||||
artists=[Artist(name=u'name2')], album=Album(name=u'name2'),
|
||||
track_no=2, date=dt.date.today()-dt.timedelta(days=1),
|
||||
length=200, bitrate=200, id=1)
|
||||
length=200, bitrate=200)
|
||||
self.assertNotEqual(track1, track2)
|
||||
self.assertNotEqual(hash(track1), hash(track2))
|
||||
|
||||
|
||||
@ -55,7 +55,7 @@ class CurrentPlaylistHandlerTest(unittest.TestCase):
|
||||
self.assert_(u'OK' in result)
|
||||
|
||||
def test_addid_with_songpos_out_of_bounds_should_ack(self):
|
||||
needle = Track(uri='dummy://foo', id=137)
|
||||
needle = Track(uri='dummy://foo')
|
||||
self.b.library._library = [Track(), Track(), needle, Track()]
|
||||
self.b.current_playlist.load(
|
||||
[Track(), Track(), Track(), Track(), Track()])
|
||||
@ -78,9 +78,10 @@ class CurrentPlaylistHandlerTest(unittest.TestCase):
|
||||
|
||||
def test_delete_songpos(self):
|
||||
self.b.current_playlist.load(
|
||||
[Track(id=1), Track(id=2), Track(id=3), Track(id=4), Track(id=5)])
|
||||
[Track(), Track(), Track(), Track(), Track()])
|
||||
self.assertEqual(len(self.b.current_playlist.tracks), 5)
|
||||
result = self.h.handle_request(u'delete "2"')
|
||||
result = self.h.handle_request(u'delete "%d"' %
|
||||
self.b.current_playlist.cp_tracks[2][0])
|
||||
self.assertEqual(len(self.b.current_playlist.tracks), 4)
|
||||
self.assert_(u'OK' in result)
|
||||
|
||||
@ -94,7 +95,7 @@ class CurrentPlaylistHandlerTest(unittest.TestCase):
|
||||
|
||||
def test_delete_open_range(self):
|
||||
self.b.current_playlist.load(
|
||||
[Track(id=1), Track(id=2), Track(id=3), Track(id=4), Track(id=5)])
|
||||
[Track(), Track(), Track(), Track(), Track()])
|
||||
self.assertEqual(len(self.b.current_playlist.tracks), 5)
|
||||
result = self.h.handle_request(u'delete "1:"')
|
||||
self.assertEqual(len(self.b.current_playlist.tracks), 1)
|
||||
@ -102,7 +103,7 @@ class CurrentPlaylistHandlerTest(unittest.TestCase):
|
||||
|
||||
def test_delete_closed_range(self):
|
||||
self.b.current_playlist.load(
|
||||
[Track(id=1), Track(id=2), Track(id=3), Track(id=4), Track(id=5)])
|
||||
[Track(), Track(), Track(), Track(), Track()])
|
||||
self.assertEqual(len(self.b.current_playlist.tracks), 5)
|
||||
result = self.h.handle_request(u'delete "1:3"')
|
||||
self.assertEqual(len(self.b.current_playlist.tracks), 3)
|
||||
|
||||
@ -146,7 +146,7 @@ expected_tracks = []
|
||||
def generate_track(path, ident):
|
||||
uri = path_to_uri(data_folder(path))
|
||||
track = Track(name='trackname', artists=expected_artists, track_no=1,
|
||||
album=expected_albums[0], length=4000, uri=uri, id=ident)
|
||||
album=expected_albums[0], length=4000, uri=uri)
|
||||
expected_tracks.append(track)
|
||||
|
||||
generate_track('song1.mp3', 6)
|
||||
@ -170,7 +170,7 @@ class MPDTagCacheToTracksTest(unittest.TestCase):
|
||||
data_folder(''))
|
||||
uri = path_to_uri(data_folder('song1.mp3'))
|
||||
track = Track(name='trackname', artists=expected_artists, track_no=1,
|
||||
album=expected_albums[0], length=4000, uri=uri, id=0)
|
||||
album=expected_albums[0], length=4000, uri=uri)
|
||||
self.assertEqual(set([track]), tracks)
|
||||
|
||||
def test_advanced_cache(self):
|
||||
@ -189,4 +189,4 @@ class MPDTagCacheToTracksTest(unittest.TestCase):
|
||||
tracks = parse_mpd_tag_cache(data_folder('blank_tag_cache'),
|
||||
data_folder(''))
|
||||
uri = path_to_uri(data_folder('song1.mp3'))
|
||||
self.assertEqual(set([Track(uri=uri, length=4000, id=0)]), tracks)
|
||||
self.assertEqual(set([Track(uri=uri, length=4000)]), tracks)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user