コード例 #1
0
    def setUp(self):
        # Testing locally is VERY dangerous without this...
        self.assertTrue(_TEMP_DIR in PLAYLISTS or os.name == "nt",
                        msg="Failing, don't want to delete %s" % PLAYLISTS)
        try:
            shutil.rmtree(PLAYLISTS)
        except OSError:
            pass

        mkdir(PLAYLISTS)

        self.lib = quodlibet.browsers.playlists.library = SongLibrary()
        self.lib.librarian = SongLibrarian()
        all_songs = SONGS + [self.ANOTHER_SONG]
        for af in all_songs:
            af.sanitize()
        self.lib.add(all_songs)

        self.big = pl = Playlist.new(PLAYLISTS, "Big", self.lib)
        pl.extend(SONGS)
        pl.write()

        self.small = pl = Playlist.new(PLAYLISTS, "Small", self.lib)
        pl.extend([self.ANOTHER_SONG])
        pl.write()

        PlaylistsBrowser.init(self.lib)

        self.bar = PlaylistsBrowser(self.lib)
        self.bar.connect('songs-selected', self._expected)
        self.bar._select_playlist(self.bar.playlists()[0])
        self.expected = None
コード例 #2
0
 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()
コード例 #3
0
    def setUp(self):
        try:
            shutil.rmtree(PLAYLISTS)
        except OSError:
            pass

        mkdir(PLAYLISTS)

        self.lib = quodlibet.browsers.playlists.library = SongLibrary()
        self.lib.librarian = SongLibrarian()
        all_songs = SONGS + [self.ANOTHER_SONG]
        for af in all_songs:
            af.sanitize()
        self.lib.add(all_songs)

        pl = Playlist.new(PLAYLISTS, "Big", self.lib)
        pl.extend(SONGS)
        pl.write()

        pl = Playlist.new(PLAYLISTS, "Small", self.lib)
        pl.extend([self.ANOTHER_SONG])
        pl.write()

        PlaylistsBrowser.init(self.lib)

        self.bar = PlaylistsBrowser(self.lib)
        self.bar.connect('songs-selected', self._expected)
        self.bar._select_playlist(self.bar.playlists()[0])
        self.expected = None
コード例 #4
0
 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])))
コード例 #5
0
 def test_make_dup(self):
     p1 = Playlist.new(self.temp, "Does not exist")
     p2 = Playlist.new(self.temp, "Does not exist")
     self.failUnlessEqual(p1.name, "Does not exist")
     self.failUnless(p2.name.startswith("Does not exist"))
     self.failIfEqual(p1.name, p2.name)
     p1.delete()
     p2.delete()
コード例 #6
0
 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()
コード例 #7
0
ファイル: test_util_collection.py プロジェクト: bp0/quodlibet
 def test_playlists_featuring(s):
     with s.wrap("playlist") as pl:
         pl.extend(NUMERIC_SONGS)
         playlists = Playlist.playlists_featuring(NUMERIC_SONGS[0])
         s.failUnlessEqual(set(playlists), {pl})
         # Now add a second one, check that instance tracking works
         with s.wrap("playlist2") as pl2:
             pl2.append(NUMERIC_SONGS[0])
             playlists = Playlist.playlists_featuring(NUMERIC_SONGS[0])
             s.failUnlessEqual(set(playlists), {pl, pl2})
コード例 #8
0
    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("~#"), "")
コード例 #9
0
 def setup():
     Playlist._remove_all()
     for i in xrange(NUM_PLAYLISTS):
         pls.append(Playlist(PLAYLISTS, "List %d" % (i+1)))
     for i in xrange(NUM_SONGS):
         a = ARTISTS[randint(0,2)]
         t = "Song %d" % i
         data = {"title": t, "artist":a, "~#tracknumber": i % 20,
                 "~filename": "%s.mp3" % t,
                 "~#filesize":randint(1000000,100000000)}
         song = Fakesong(data)
         library.append(song)
         if not (i % SONGS_TO_PLAYLIST_SIZE_RATIO):
             song["~included"] = "yes"
             for j in range(PLAYLISTS_PER_PLAYLISTED_SONG):
                 pls[(i+j) % NUM_PLAYLISTS].append(song)
コード例 #10
0
ファイル: util.py プロジェクト: SimonLarsen/quodlibet
def __parse_playlist(name, plfilename, files, library):
    playlist = Playlist.new(PLAYLISTS, name, library=library)
    songs = []
    win = WaitLoadWindow(None, len(files), _("Importing playlist.\n\n%(current)d/%(total)d songs added."))
    win.show()
    for i, filename in enumerate(files):
        try:
            uri = URI(filename)
        except ValueError:
            if os.name == "nt":
                filename = filename.decode("utf-8", "replace")
            # Plain filename.
            filename = os.path.realpath(os.path.join(os.path.dirname(plfilename), filename))
            if library and filename in library:
                songs.append(library[filename])
            else:
                songs.append(formats.MusicFile(filename))
        else:
            if uri.scheme == "file":
                # URI-encoded local filename.
                filename = os.path.realpath(os.path.join(os.path.dirname(plfilename), uri.filename))
                if library and filename in library:
                    songs.append(library[filename])
                else:
                    songs.append(formats.MusicFile(filename))
            else:
                # Who knows! Hand it off to GStreamer.
                songs.append(formats.remote.RemoteFile(uri))
        if win.step():
            break
    win.destroy()
    playlist.extend(filter(None, songs))
    return playlist
コード例 #11
0
    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)
コード例 #12
0
    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"))
コード例 #13
0
ファイル: menu.py プロジェクト: achadwick/quodlibet
 def _on_new_playlist_activate(self, item, songs):
     parent = get_menu_item_top_parent(item)
     title = Playlist.suggested_name_for(songs)
     title = GetPlaylistName(qltk.get_top_parent(parent)).run(title)
     if title is None:
         return
     playlist = FileBackedPlaylist.new(PLAYLISTS, title)
     playlist.extend(songs)
     PlaylistsBrowser.changed(playlist)
コード例 #14
0
ファイル: menu.py プロジェクト: ZDBioHazard/quodlibet
 def _on_new_playlist_activate(self, item, songs):
     parent = get_menu_item_top_parent(item)
     title = Playlist.suggested_name_for(songs)
     title = self._get_new_name(parent, title)
     if title is None:
         return
     playlist = FileBackedPlaylist.new(PLAYLISTS, title,
                                       library=self.librarian)
     playlist.extend(songs)
     self._emit_new(playlist)
コード例 #15
0
 def setUp(self):
     quodlibet.config.init()
     self.lib = quodlibet.browsers.search.library = FileLibrary()
     quodlibet.browsers.search.library.librarian = SongLibrarian()
     for af in self.SONGS:
         af.sanitize()
     self.lib.add(self.SONGS)
     self._dir = mkdtemp()
     self.pl = Playlist.new(self._dir, "Foobar", self.lib)
     self.pl.extend(self.SONGS)
コード例 #16
0
ファイル: main.py プロジェクト: brunob/quodlibet
 def __drag_data_received(self, view, ctx, x, y, sel, tid, etime, library):
     # TreeModelSort doesn't support GtkTreeDragDestDrop.
     view.emit_stop_by_name('drag-data-received')
     model = view.get_model()
     if tid == DND_QL:
         filenames = qltk.selection_get_filenames(sel)
         songs = filter(None, map(library.get, filenames))
         if not songs:
             Gtk.drag_finish(ctx, False, False, etime)
             return
         try:
             path, pos = view.get_dest_row_at_pos(x, y)
         except TypeError:
             playlist = Playlist.fromsongs(PLAYLISTS, songs, library)
             GLib.idle_add(self.__select_playlist, playlist)
         else:
             playlist = model[path][0]
             playlist.extend(songs)
         PlaylistsBrowser.changed(playlist)
         Gtk.drag_finish(ctx, True, False, etime)
     else:
         if tid == DND_URI_LIST:
             uri = sel.get_uris()[0]
             name = os.path.basename(uri)
         elif tid == DND_MOZ_URL:
             data = sel.get_data()
             uri, name = data.decode('utf16', 'replace').split('\n')
         else:
             Gtk.drag_finish(ctx, False, False, etime)
             return
         name = name or os.path.basename(uri) or _("New Playlist")
         uri = uri.encode('utf-8')
         try:
             sock = urllib.urlopen(uri)
             f = NamedTemporaryFile()
             f.write(sock.read())
             f.flush()
             if uri.lower().endswith('.pls'):
                 playlist = parse_pls(f.name, library=library)
             elif uri.lower().endswith('.m3u'):
                 playlist = parse_m3u(f.name, library=library)
             else:
                 raise IOError
             library.add_filename(playlist)
             if name:
                 playlist.rename(name)
             PlaylistsBrowser.changed(playlist)
             Gtk.drag_finish(ctx, True, False, etime)
         except IOError:
             Gtk.drag_finish(ctx, False, False, etime)
             qltk.ErrorMessage(
                 qltk.get_top_parent(self),
                 _("Unable to import playlist"),
                 _("Quod Libet can only import playlists in the M3U "
                   "and PLS formats.")).run()
コード例 #17
0
    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))
コード例 #18
0
    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)
コード例 #19
0
    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)
コード例 #20
0
ファイル: main.py プロジェクト: brunob/quodlibet
 def reordered(self, songs):
     model, iter = self.__view.get_selection().get_selected()
     playlist = None
     if iter:
         playlist = model[iter][0]
         playlist[:] = songs
     elif songs:
         playlist = Playlist.fromsongs(PLAYLISTS, songs)
         GLib.idle_add(self.__select_playlist, playlist)
     if playlist:
         PlaylistsBrowser.changed(playlist, refresh=False)
コード例 #21
0
 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"))
コード例 #22
0
ファイル: main.py プロジェクト: brunob/quodlibet
 def init(klass, library):
     model = klass.__lists.get_model()
     for playlist in os.listdir(PLAYLISTS):
         try:
             playlist = Playlist(PLAYLISTS, Playlist.unquote(playlist),
                                 library=library)
             model.append(row=[playlist])
         except EnvironmentError:
             pass
     library.connect('removed', klass.__removed)
     library.connect('added', klass.__added)
     library.connect('changed', klass.__changed)
コード例 #23
0
 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()
コード例 #24
0
    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))
コード例 #25
0
ファイル: playlists.py プロジェクト: silkecho/glowing-silk
 def __add_to_playlist(playlist, songs, parent):
     if playlist is None:
         if len(songs) == 1:
             title = songs[0].comma("title")
         else:
             title = ngettext(
                 "%(title)s and %(count)d more",
                 "%(title)s and %(count)d more",
                 len(songs) - 1) % (
                 {'title': songs[0].comma("title"), 'count': len(songs) - 1})
         title = GetPlaylistName(qltk.get_top_parent(parent)).run(title)
         if title is None: return
         playlist = Playlist.new(PLAYLISTS, title)
     playlist.extend(songs)
     Playlists.changed(playlist)
コード例 #26
0
ファイル: menu.py プロジェクト: mistotebe/quodlibet
    def _on_new_playlist_activate(self, item, songs):
        parent = get_menu_item_top_parent(item)

        if len(songs) == 1:
            title = songs[0].comma("title")
        else:
            title = ngettext(
                "%(title)s and %(count)d more",
                "%(title)s and %(count)d more",
                len(songs) - 1) % {
                    'title': songs[0].comma("title"),
                    'count': len(songs) - 1
                }
        title = GetPlaylistName(qltk.get_top_parent(parent)).run(title)
        if title is None:
            return
        playlist = Playlist.new(PLAYLISTS, title)
        playlist.extend(songs)
        PlaylistsBrowser.changed(playlist)
コード例 #27
0
 def test_rename_working(self):
     p1 = Playlist.new(self.temp, "Foobar")
     p1.rename("Foo Quuxly")
     self.failUnlessEqual(p1.name, "Foo Quuxly")
     p1.delete()
コード例 #28
0
 def test_rename_nothing(self):
     p1 = Playlist.new(self.temp, "Foobar")
     self.failUnlessRaises(ValueError, p1.rename, "")
     p1.delete()
コード例 #29
0
    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()
コード例 #30
0
import os
import shutil

from gi.repository import Gtk
from quodlibet.browsers import Browser

from quodlibet.library import SongLibrary
from quodlibet.plugins.playlist import PlaylistPlugin, PlaylistPluginHandler
from quodlibet.util.collection import Playlist
from tests import TestCase, mkstemp, mkdtemp
from quodlibet.plugins import PluginManager, Plugin
from tests.helper import capture_output

MAX_PLAYLISTS = 50
TEST_PLAYLIST = Playlist("foo")


def generate_playlists(n):
    return [Playlist("Playlist %d" % x) for x in range(n)]


class TPlaylistPlugins(TestCase):

    class MockBrowser(Browser):
        def __init__(self):
            super(TPlaylistPlugins.MockBrowser, self).__init__()
            self.activated = False

        def activate(self):
            self.activated = True
コード例 #31
0
 def test_duplicates_single_item(self):
     pl = Playlist(self.temp, "playlist")
     pl.append(self.TWO_SONGS[0])
     self.failIf(pl.has_duplicates)
     pl.append(self.TWO_SONGS[0])
     self.failUnless(pl.has_duplicates)
コード例 #32
0
 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()
コード例 #33
0
def generate_playlists(n):
    return [Playlist(DIR, "Playlist %d" % x) for x in range(n)]
コード例 #34
0
    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()
コード例 #35
0
    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()
コード例 #36
0
 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()
コード例 #37
0
 def test_duplicates_single_item(self):
     pl = Playlist(self.temp, "playlist")
     pl.append(self.TWO_SONGS[0])
     self.failIf(pl.has_duplicates)
     pl.append(self.TWO_SONGS[0])
     self.failUnless(pl.has_duplicates)
コード例 #38
0
 def pl(self, name, lib=None) -> Playlist:
     return Playlist(name, lib)
コード例 #39
0
 def test_make(self):
     p1 = Playlist.new(self.temp, "Does not exist")
     self.failUnlessEqual(0, len(p1))
     self.failUnlessEqual(p1.name, "Does not exist")
     p1.delete()
コード例 #40
0
 def test_equality(s):
     pl = Playlist(s.temp, "playlist")
     pl2 = Playlist(s.temp, "playlist")
     pl3 = Playlist(s.temp2, "playlist")
     s.failUnlessEqual(pl, pl2)
     # Debatable
     s.failUnlessEqual(pl, pl3)
     pl4 = Playlist(s.temp, "foobar")
     s.failIfEqual(pl, pl4)
     pl.delete()
     pl2.delete()
     pl3.delete()
     pl4.delete()
コード例 #41
0
ファイル: main.py プロジェクト: ch1huizong/scode
 def __new_playlist(self, activator):
     playlist = Playlist.new(PLAYLISTS)
     self.__lists.get_model().append(row=[playlist])
     self.__select_playlist(playlist)
コード例 #42
0
    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()
コード例 #43
0
 def _create_temp_playlist_with(cls, name, songs):
     pl = Playlist.new(PLAYLISTS, name, cls.lib)
     pl.extend(songs)
     pl.write()
コード例 #44
0
 def test_equality(s):
     pl = Playlist(s.temp, "playlist")
     pl2 = Playlist(s.temp, "playlist")
     pl3 = Playlist(s.temp2, "playlist")
     s.failUnlessEqual(pl, pl2)
     # Debatable
     s.failUnlessEqual(pl, pl3)
     pl4 = Playlist(s.temp, "foobar")
     s.failIfEqual(pl, pl4)
     pl.delete()
     pl2.delete()
     pl3.delete()
     pl4.delete()
コード例 #45
0
import os
import shutil

from gi.repository import Gtk
from quodlibet.browsers import Browser

from quodlibet.library import SongLibrary
from quodlibet.plugins.playlist import PlaylistPlugin, PlaylistPluginHandler
from quodlibet.util.collection import Playlist
from tests import TestCase, mkstemp, mkdtemp
from quodlibet.plugins import PluginManager, Plugin
from tests.helper import capture_output

MAX_PLAYLISTS = 50
DIR = mkdtemp()
TEST_PLAYLIST = Playlist(DIR, "foo")


def generate_playlists(n):
    return [Playlist(DIR, "Playlist %d" % x) for x in range(n)]


class TPlaylistPlugins(TestCase):
    class MockBrowser(Browser):
        def __init__(self):
            super(TPlaylistPlugins.MockBrowser, self).__init__()
            self.activated = False

        def activate(self):
            self.activated = True
コード例 #46
0
 def test_rename_dup(self):
     p1 = Playlist.new(self.temp, "Foobar")
     p2 = Playlist.new(self.temp, "Crazy")
     self.failUnlessRaises(ValueError, p2.rename, "Foobar")
     p1.delete()
     p2.delete()
コード例 #47
0
ファイル: _audio.py プロジェクト: mkalinski/quodlibet
    def __call__(self, key, default=u"", connector=" - ", joiner=', '):
        """Return the value(s) for a key, synthesizing if necessary.
        Multiple values for a key are delimited by newlines.

        A default value may be given (like `dict.get`);
        the default default is an empty unicode string
        (even if the tag is numeric).

        If a tied tag ('a~b') is requested, the `connector` keyword
        argument may be used to specify what it is tied with.
        In case the tied tag contains numeric and file path tags, the result
        will still be a unicode string.
        The `joiner` keyword specifies how multiple *values* will be joined
        within that tied tag output, e.g.
            ~people~title = "Kanye West, Jay Z - New Day"

        For details on tied tags, see the documentation for `util.tagsplit`.
        """

        if key[:1] == "~":
            key = key[1:]
            if "~" in key:
                real_key = "~" + key
                values = []
                sub_tags = util.tagsplit(real_key)
                # If it's genuinely a tied tag (not ~~people etc), we want
                # to delimit the multi-values separately from the tying
                j = joiner if len(sub_tags) > 1 else "\n"
                for t in sub_tags:
                    vs = [decode_value(real_key, v) for v in (self.list(t))]
                    v = j.join(vs)
                    if v:
                        values.append(v)
                return connector.join(values) or default
            elif key == "#track":
                try:
                    return int(self["tracknumber"].split("/")[0])
                except (ValueError, TypeError, KeyError):
                    return default
            elif key == "#disc":
                try:
                    return int(self["discnumber"].split("/")[0])
                except (ValueError, TypeError, KeyError):
                    return default
            elif key == "length":
                length = self.get("~#length")
                if length is None:
                    return default
                else:
                    return util.format_time_display(length)
            elif key == "#rating":
                return dict.get(self, "~" + key, config.RATINGS.default)
            elif key == "rating":
                return util.format_rating(self("~#rating"))
            elif key == "people":
                return "\n".join(self.list_unique(PEOPLE)) or default
            elif key == "people:real":
                # Issue 1034: Allow removal of V.A. if others exist.
                unique = self.list_unique(PEOPLE)
                # Order is important, for (unlikely case): multiple removals
                for val in VARIOUS_ARTISTS_VALUES:
                    if len(unique) > 1 and val in unique:
                        unique.remove(val)
                return "\n".join(unique) or default
            elif key == "people:roles":
                return (self._role_call("performer", PEOPLE) or default)
            elif key == "peoplesort":
                return ("\n".join(self.list_unique(PEOPLE_SORT))
                        or self("~people", default, connector))
            elif key == "peoplesort:roles":
                # Ignores non-sort tags if there are any sort tags (e.g. just
                # returns "B" for {artist=A, performersort=B}).
                # TODO: figure out the "correct" behavior for mixed sort tags
                return (self._role_call("performersort", PEOPLE_SORT)
                        or self("~peoplesort", default, connector))
            elif key in ("performers", "performer"):
                return self._prefixvalue("performer") or default
            elif key in ("performerssort", "performersort"):
                return (self._prefixvalue("performersort")
                        or self("~" + key[-4:], default, connector))
            elif key in ("performers:roles", "performer:roles"):
                return (self._role_call("performer") or default)
            elif key in ("performerssort:roles", "performersort:roles"):
                return (self._role_call("performersort") or self(
                    "~" + key.replace("sort", ""), default, connector))
            elif key == "basename":
                return os.path.basename(self["~filename"]) or self["~filename"]
            elif key == "dirname":
                return os.path.dirname(self["~filename"]) or self["~filename"]
            elif key == "uri":
                try:
                    return self["~uri"]
                except KeyError:
                    return fsn2uri(self["~filename"])
            elif key == "format":
                return self.get("~format", str(self.format))
            elif key == "codec":
                codec = self.get("~codec")
                if codec is None:
                    return self("~format")
                return codec
            elif key == "encoding":
                parts = filter(None,
                               [self.get("~encoding"),
                                self.get("encodedby")])
                encoding = u"\n".join(parts)
                return encoding or default
            elif key == "language":
                codes = self.list("language")
                if not codes:
                    return default
                return u"\n".join(iso639.translate(c) or c for c in codes)
            elif key == "bitrate":
                return util.format_bitrate(self("~#bitrate"))
            elif key == "#date":
                date = self.get("date")
                if date is None:
                    return default
                return util.date_key(date)
            elif key == "year":
                return self.get("date", default)[:4]
            elif key == "#year":
                try:
                    return int(self.get("date", default)[:4])
                except (ValueError, TypeError, KeyError):
                    return default
            elif key == "originalyear":
                return self.get("originaldate", default)[:4]
            elif key == "#originalyear":
                try:
                    return int(self.get("originaldate", default)[:4])
                except (ValueError, TypeError, KeyError):
                    return default
            elif key == "#tracks":
                try:
                    return int(self["tracknumber"].split("/")[1])
                except (ValueError, IndexError, TypeError, KeyError):
                    return default
            elif key == "#discs":
                try:
                    return int(self["discnumber"].split("/")[1])
                except (ValueError, IndexError, TypeError, KeyError):
                    return default
            elif key == "lyrics":
                # First, try the embedded lyrics.
                try:
                    return self["lyrics"]
                except KeyError:
                    pass

                try:
                    return self["unsyncedlyrics"]
                except KeyError:
                    pass

                # If there are no embedded lyrics, try to read them from
                # the external file.
                try:
                    with open(self.lyric_filename, "rb") as fileobj:
                        print_d("Reading lyrics from %s" % self.lyric_filename)
                        text = fileobj.read().decode("utf-8", "replace")
                        # try to skip binary files
                        if "\0" in text:
                            return default
                        return text
                except EnvironmentError:
                    return default
            elif key == "filesize":
                return util.format_size(self("~#filesize", 0))
            elif key == "playlists":
                # See Issue 876
                # Avoid circular references from formats/__init__.py
                from quodlibet.util.collection import Playlist
                playlists = Playlist.playlists_featuring(self)
                return "\n".join(s.name for s in playlists) or default
            elif key.startswith("#replaygain_"):
                try:
                    val = self.get(key[1:], default)
                    return round(float(val.split(" ")[0]), 2)
                except (ValueError, TypeError, AttributeError):
                    return default
            elif key[:1] == "#":
                key = "~" + key
                if key in self:
                    return self[key]
                elif key in NUMERIC_ZERO_DEFAULT:
                    return 0
                else:
                    try:
                        val = self[key[2:]]
                    except KeyError:
                        return default
                    try:
                        return int(val)
                    except ValueError:
                        try:
                            return float(val)
                        except ValueError:
                            return default
            else:
                return dict.get(self, "~" + key, default)

        elif key == "title":
            title = dict.get(self, "title")
            if title is None:
                basename = self("~basename")
                return "%s [%s]" % (decode_value("~basename",
                                                 basename), _("Unknown"))
            else:
                return title
        elif key in SORT_TO_TAG:
            try:
                return self[key]
            except KeyError:
                key = SORT_TO_TAG[key]
        return dict.get(self, key, default)
コード例 #48
0
 def test_remove_no_lib(self):
     pl = Playlist.new(self._dir, "Foobar")
     pl.extend(self.SONGS)
     self.assertTrue(len(pl))
     pl.remove_songs(self.SONGS, False)
     self.assertFalse(len(pl))