def test_updating_aggregates_remove_songs(s): pl = Playlist(s.temp, "playlist") pl.extend(NUMERIC_SONGS) s.failUnless(pl.get("~#length")) pl.remove_songs(NUMERIC_SONGS) s.failIf(pl.get("~#length"))
def test_masked_handling(self): if os.name == "nt": # FIXME: masking isn't properly implemented on Windows return # playlists can contain songs and paths for masked handling.. lib = FileLibrary("foobar") pl = Playlist(self.temp, "playlist", lib) song = Fakesong({"date": "2038", "~filename": fsnative(u"/fake")}) song.sanitize() lib.add([song]) # mask and update lib.mask("/") pl.append(song) pl.remove_songs([song]) self.failUnless("/fake" in pl) pl.extend(self.TWO_SONGS) # check if collections can handle the mix self.failUnlessEqual(pl("date"), "2038") # unmask and update lib.unmask("/") pl.add_songs(["/fake"], lib) self.failUnless(song in pl) pl.delete() lib.destroy()
def test_listlike(s): pl = Playlist(s.temp, "playlist") pl.extend(NUMERIC_SONGS) s.failUnlessEqual(NUMERIC_SONGS[0], pl[0]) s.failUnlessEqual(NUMERIC_SONGS[1:2], pl[1:2]) s.failUnless(NUMERIC_SONGS[1] in pl) pl.delete()
def test_masked_handling(self): if os.name == "nt": # FIXME: masking isn't properly implemented on Windows return # playlists can contain songs and paths for masked handling.. lib = FileLibrary("foobar") pl = Playlist(self.temp, "playlist", lib) song = Fakesong({"date": "2038", "~filename": "/fake"}) song.sanitize() lib.add([song]) # mask and update lib.mask("/") pl.append(song) pl.remove_songs([song]) self.failUnless("/fake" in pl) pl.extend(self.TWO_SONGS) # check if collections can handle the mix self.failUnlessEqual(pl("date"), "2038") # unmask and update lib.unmask("/") pl.add_songs(["/fake"], lib) self.failUnless(song in pl) pl.delete() lib.destroy()
def test_duplicates(self): pl = Playlist(self.temp, "playlist") pl.extend(self.TWO_SONGS) pl.extend(self.TWO_SONGS) self.failUnlessEqual(len(pl), 4) self.failUnless(pl.has_duplicates, ("Playlist has un-detected duplicates: %s " % "\n".join([str(s) for s in pl._list])))
def test_read(self): pl = Playlist(self.temp, "playlist") pl.extend(NUMERIC_SONGS) pl.write() lib = FileLibrary("foobar") lib.add(NUMERIC_SONGS) pl = Playlist(self.temp, "playlist", lib) self.assertEqual(len(pl), len(NUMERIC_SONGS))
def test_write(self): pl = Playlist(self.temp, "playlist") pl.extend(NUMERIC_SONGS) pl.extend([fsnative(u"xf0xf0")]) pl.write() with open(pl.filename, "rb") as h: self.assertEqual(len(h.read().splitlines()), len(NUMERIC_SONGS) + 1)
def test_updating_aggregates_append(s): pl = Playlist(s.temp, "playlist") pl.extend(NUMERIC_SONGS) old_rating = pl.get("~#rating") pl.append(AMAZING_SONG) new_rating = pl.get("~#filesize") s.failUnless(new_rating > old_rating)
def test_playlists_tag(self): # Arguably belongs in _audio songs = NUMERIC_SONGS pl_name = "playlist 123!" pl = Playlist(self.temp, pl_name) pl.extend(songs) for song in songs: self.assertEquals(pl_name, song("~playlists")) pl.delete()
def test_playlists_tag(self): # Arguably belongs in _audio songs = NUMERIC_SONGS Playlist._remove_all() Playlist._clear_global_cache() pl_name="playlist 123!" pl = Playlist(self.temp, pl_name) pl.extend(songs) for song in songs: self.assertEquals(pl_name, song("~playlists"))
def test_playlists_featuring(s): pl = Playlist(s.temp, "playlist") pl.extend(NUMERIC_SONGS) playlists = Playlist.playlists_featuring(NUMERIC_SONGS[0]) s.failUnlessEqual(set(playlists), set([pl])) # Now add a second one, check that instance tracking works pl2 = Playlist(s.temp, "playlist2") pl2.append(NUMERIC_SONGS[0]) playlists = Playlist.playlists_featuring(NUMERIC_SONGS[0]) s.failUnlessEqual(set(playlists), set([pl, pl2])) pl.delete() pl2.delete()
def test_internal_tags(s): pl = Playlist(s.temp, "playlist") pl.extend(s.TWO_SONGS) s.failIfEqual(pl.comma("~long-length"), "") s.failIfEqual(pl.comma("~tracks"), "") s.failIfEqual(pl.comma("~discs"), "") s.failUnlessEqual(pl.comma("~foo"), "") s.failUnlessEqual(pl.comma(""), "") s.failUnlessEqual(pl.comma("~"), "") s.failUnlessEqual(pl.get("~#"), "")
def test_playlists_featuring(s): Playlist._remove_all() Playlist._clear_global_cache() pl = Playlist(s.temp, "playlist") pl.extend(NUMERIC_SONGS) playlists = Playlist.playlists_featuring(NUMERIC_SONGS[0]) s.failUnlessEqual(playlists, set([pl])) # Now add a second one, check that instance tracking works pl2 = Playlist(s.temp, "playlist2") pl2.append(NUMERIC_SONGS[0]) playlists = Playlist.playlists_featuring(NUMERIC_SONGS[0]) s.failUnlessEqual(playlists, set([pl, pl2]))
def test_internal_tags(s): pl = Playlist(s.temp, "playlist") pl.extend(s.TWO_SONGS) s.failIfEqual(pl.comma("~long-length"), "") s.failIfEqual(pl.comma("~tracks"), "") s.failIfEqual(pl.comma("~discs"), "") s.failUnlessEqual(pl.comma("~foo"), "") s.failUnlessEqual(pl.comma(""), "") s.failUnlessEqual(pl.comma("~"), "") s.failUnlessEqual(pl.get("~#"), "") pl.delete()
def test_index(s): pl = Playlist(s.temp, "playlist") songs = s.TWO_SONGS pl.extend(songs) # Just a sanity check... s.failUnlessEqual(1, songs.index(songs[1])) # And now the happy paths.. s.failUnlessEqual(0, pl.index(songs[0])) s.failUnlessEqual(1, pl.index(songs[1])) # ValueError is what we want here try: pl.index(Fakesong({})) s.fail() except ValueError: pass
def test_updating_aggregates_extend(s): pl = Playlist(s.temp, "playlist") pl.extend(NUMERIC_SONGS) old_length = pl.get("~#length") old_size = pl.get("~#filesize") # Double the playlist pl.extend(NUMERIC_SONGS) new_length = pl.get("~#length") new_size = pl.get("~#filesize") s.failUnless(new_length > old_length, msg="Ooops, %d <= %d" % (new_length, old_length)) s.failUnless(new_size > old_size, msg="Ooops, %d <= %d" % (new_size, old_size))
def test_index(s): pl = Playlist(s.temp, "playlist") songs = s.TWO_SONGS pl.extend(songs) # Just a sanity check... s.failUnlessEqual(1, songs.index(songs[1])) # And now the happy paths.. s.failUnlessEqual(0, pl.index(songs[0])) s.failUnlessEqual(1, pl.index(songs[1])) # ValueError is what we want here try: pl.index(Fakesong({})) s.fail() except ValueError: pass pl.delete()
def test_playlist_plugin(self): pl = Playlist("foo", library=app.librarian) pl.extend([AudioFile({"~filename": "/dev/null"})]) self.called_pl = None self.called_songs = None def proxy(songs, playlist=None): self.called_pl = playlist self.called_songs = songs plugin = self.plugin(playlists=[pl]) plugin._handle_songs = proxy # Test that as a Playlist plugin it delegates correctly plugin.plugin_playlist(pl) self.failUnless(self.called_songs) self.assertEqual(self.called_pl, pl) self.assertEqual(self.called_songs, pl.songs)
def test_playlist_plugin(self): pl = Playlist("foo", library=app.librarian) pl.extend([AudioFile({"~filename": "/dev/null"})]) self.called_pl = None self.called_songs = None def proxy(songs, playlist=None): self.called_pl = playlist self.called_songs = songs plugin = self.plugin() plugin._handle_songs = proxy # Test that as a Playlist plugin it delegates correctly plugin.plugin_playlist(pl) self.failUnless(self.called_songs) self.assertEqual(self.called_pl, pl) self.assertEqual(self.called_songs, pl.songs)
def test_numeric_ops(s): songs = NUMERIC_SONGS pl = Playlist(s.temp, "playlist") pl.extend(songs) s.failUnlessEqual(pl.get("~#length"), 12) s.failUnlessEqual(pl.get("~#length:sum"), 12) s.failUnlessEqual(pl.get("~#length:max"), 7) s.failUnlessEqual(pl.get("~#length:min"), 1) s.failUnlessEqual(pl.get("~#length:avg"), 4) s.failUnlessEqual(pl.get("~#length:foo"), 0) s.failUnlessEqual(pl.get("~#filesize"), 303) s.failUnlessEqual(pl.get("~#added"), 7) s.failUnlessEqual(pl.get("~#lastplayed"), 88) s.failUnlessEqual(pl.get("~#bitrate"), 200) s.failUnlessEqual(pl.get("~#year"), 33) s.failUnlessEqual(pl.get("~#rating"), 0.3) s.failUnlessEqual(pl.get("~#originalyear"), 2002)
def test_add_remove(self): pl = Playlist("only", self.lib, self.playlists) assert self.received == ["added", "pl_added"] self.received.clear() # Update playlist, should trigger changes in files too pl.extend(self.lib._contents.values()) # Changing files then does trigger another change, # annoying but seems impossible to avoid if we want to save metadata, ~playlists assert self.received == ["pl_changed", "changed", "pl_changed"] self.received.clear() # Remove some songs and watch the playlist change songs = list(self.lib._contents.values()) self.lib.remove(songs[:2]) assert self.received == [ "removed", "pl_changed", "changed", "pl_changed" ] self.received.clear() pl.delete() assert self.received == ["pl_removed"]
def test_numeric_ops(s): songs = NUMERIC_SONGS pl = Playlist(s.temp, "playlist") pl.extend(songs) s.failUnlessEqual(pl.get("~#length"), 12) s.failUnlessEqual(pl.get("~#length:sum"), 12) s.failUnlessEqual(pl.get("~#length:max"), 7) s.failUnlessEqual(pl.get("~#length:min"), 1) s.failUnlessEqual(pl.get("~#length:avg"), 4) s.failUnlessEqual(pl.get("~#length:foo"), 0) s.failUnlessEqual(pl.get("~#rating:avg"), avg([0.1, 0.3, 0.5])) s.failUnlessEqual(pl.get("~#filesize"), 303) s.failUnlessEqual(pl.get("~#added"), 7) s.failUnlessEqual(pl.get("~#lastplayed"), 88) s.failUnlessEqual(pl.get("~#bitrate"), 200) s.failUnlessEqual(pl.get("~#year"), 33) s.failUnlessEqual(pl.get("~#rating"), 0.3) s.failUnlessEqual(pl.get("~#originalyear"), 2002) pl.delete()
def test_playlist_info_markup(self): pl = Playlist("foobar") pl.extend(SONGS[0:2]) pat = MarkupPattern("<~name>: <artist|<artist>|?> [b]<~length>[/b]") markup = playlist_info_markup(pl, pat) self.failUnlessEqual(markup, "foobar: mu, piman <b>3:54</b>")