def test_internal_tags(s):
        songs = [
            Fakesong({
                "~#length": 5,
                "discnumber": "1",
                "date": "2038"
            }),
            Fakesong({
                "~#length": 7,
                "dummy": "d\ne",
                "discnumber": "2"
            })
        ]

        album = Album(songs[0])
        album.songs = set(songs)

        s.failIfEqual(album.comma("~long-length"), "")
        s.failIfEqual(album.comma("~tracks"), "")
        s.failIfEqual(album.comma("~discs"), "")
        s.failUnlessEqual(album.comma("~foo"), "")

        s.failUnlessEqual(album.comma(""), "")
        s.failUnlessEqual(album.comma("~"), "")
        s.failUnlessEqual(album.get("~#"), "")
    def test_tied_num_tags(s):
        songs = [
            Fakesong({
                "~#length": 5,
                "title": "c",
                "~#rating": 0.4
            }),
            Fakesong({
                "~#length": 7,
                "dummy": "d\ne",
                "~#rating": 0.6
            }),
            Fakesong({
                "~#length": 0,
                "dummy2": 5,
                "~#rating": 0.5
            })
        ]

        album = Album(songs[0])
        album.songs = set(songs)

        s.failUnlessEqual(album.comma("~foo~~s~~~"), "")
        s.failUnlessEqual(album.comma("~#length~dummy"), "12 - e, d")
        s.failUnlessEqual(album.comma("~#rating~dummy"), "0.50 - e, d")
        s.failUnlessEqual(album.comma("~#length:sum~dummy"), "12 - e, d")
        s.failUnlessEqual(album.comma("~#dummy2"), 5)
        s.failUnlessEqual(album.comma("~#dummy3"), "")
    def test_multiple_ratings(s):
        r1, r2 = 1.0, 0.5
        songs = [Fakesong({"~#rating": r1}), Fakesong({"~#rating": r2})]
        album = Album(songs[0])
        album.songs = set(songs)
        # Standard averaging still available
        s.failUnlessEqual(album("~#rating:avg"), avg([r1, r2]))

        # C = 0.0 => emulate arithmetic mean
        config.set("settings", "bayesian_rating_factor", 0.0)
        s.failUnlessEqual(album("~#rating:bav"), album("~#rating:avg"))
    def test_bayesian_multiple_ratings(s):
        # separated from above to avoid caching
        c, r1, r2 = 5, 1.0, 0.5
        songs = [Fakesong({"~#rating": r1}), Fakesong({"~#rating": r2})]
        album = Album(songs[0])
        album.songs = set(songs)

        config.set("settings", "bayesian_rating_factor", float(c))
        s.failUnlessEqual(
            config.getfloat("settings", "bayesian_rating_factor"), float(c))
        expected = avg(c * [config.RATINGS.default] + [r1, r2])
        s.failUnlessEqual(album("~#rating:bav"), expected)
        s.failUnlessEqual(album("~#rating"), expected)
    def test_tied_tags(s):
        songs = [
            Fakesong({
                "artist": "a",
                "title": "c"
            }),
            Fakesong({
                "artist": "a",
                "dummy": "d\ne"
            })
        ]

        album = Album(songs[0])
        album.songs = set(songs)

        s.failUnlessEqual(album.comma("~artist~dummy"), "a - e, d")
    def test_peoplesort_sort(s):
        songs = [
            Fakesong({
                "albumartistsort": "aa",
                "artist": "b\na"
            }),
            Fakesong({
                "albumartist": "aa",
                "artistsort": "a\na"
            })
        ]

        album = Album(songs[0])
        album.songs = set(songs)

        s.failUnlessEqual(album.comma("~peoplesort"), "aa, a, b")
    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_defaults(s):
        failUnlessEq = s.failUnlessEqual
        song = Fakesong({})
        album = Album(song)

        failUnlessEq(album("foo", "x"), "x")

        album.songs.add(song)

        failUnlessEq(album("~#length", "x"), song("~#length", "x"))
        failUnlessEq(album("~#bitrate", "x"), song("~#bitrate", "x"))
        failUnlessEq(album("~#rating", "x"), song("~#rating", "x"))
        failUnlessEq(album("~#playcount", "x"), song("~#playcount", "x"))
        failUnlessEq(album("~#mtime", "x"), song("~#mtime", "x"))
        failUnlessEq(album("~#year", "x"), song("~#year", "x"))

        failUnlessEq(album("~#foo", "x"), song("~#foo", "x"))
        failUnlessEq(album("foo", "x"), song("foo", "x"))
        failUnlessEq(album("~foo", "x"), song("~foo", "x"))

        failUnlessEq(album("~people", "x"), song("~people", "x"))
        failUnlessEq(album("~peoplesort", "x"), song("~peoplesort", "x"))
        failUnlessEq(album("~performer", "x"), song("~performer", "x"))
        failUnlessEq(album("~performersort", "x"), song("~performersort", "x"))

        failUnlessEq(album("~cover", "x"), song("~cover", "x"))
        failUnlessEq(album("~rating", "x"), song("~rating", "x"))

        for p in PEOPLE:
            failUnlessEq(album(p, "x"), song(p, "x"))

        for p in INTERN_NUM_DEFAULT:
            failUnlessEq(album(p, "x"), song(p, "x"))
 def test_single_rating(s):
     songs = [Fakesong({"~#rating": 0.75})]
     album = Album(songs[0])
     album.songs = set(songs)
     # One song should average to its own rating
     s.failUnlessEqual(album.get("~#rating:avg"), songs[0]("~#rating"))
     # BAV should now be default for rating
     s.failUnlessEqual(album.get("~#rating:bav"), album.get("~#rating:avg"))
    def test_methods(s):
        songs = [
            Fakesong({
                "b": "bb4\nbb1\nbb1",
                "c": "cc1\ncc3\ncc3"
            }),
            Fakesong({
                "b": "bb1\nbb1\nbb4",
                "c": "cc3\ncc1\ncc3"
            })
        ]

        album = Album(songs[0])
        album.songs = set(songs)

        s.failUnlessEqual(album.list("c"), ["cc3", "cc1"])
        s.failUnlessEqual(album.list("~c~b"), ["cc3", "cc1", "bb1", "bb4"])

        s.failUnlessEqual(album.comma("c"), "cc3, cc1")
        s.failUnlessEqual(album.comma("~c~b"), "cc3, cc1 - bb1, bb4")
 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_numeric_comma(self):
        songs = [
            Fakesong({
                "~#added": long(1),
                "~#rating": 0.5,
                "~#bitrate": 42,
                "~#length": 1,
            })
        ]

        album = Album(songs[0])
        album.songs = set(songs)

        self.assertEqual(album.comma("~#added"), 1)
        self.assertEqual(album.comma("~#rating"), 0.5)
        self.assertEqual(album.comma("~#bitrate"), 42)
class TPlaylist(TestCase):
    TWO_SONGS = [
        Fakesong({
            "~#length": 5,
            "discnumber": "1",
            "date": "2038"
        }),
        Fakesong({
            "~#length": 7,
            "dummy": "d\ne",
            "discnumber": "2"
        })
    ]

    def setUp(self):
        self.temp = mkdtemp()
        self.temp2 = mkdtemp()

    def tearDown(self):
        shutil.rmtree(self.temp)
        shutil.rmtree(self.temp2)

    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()

    def test_rename_working(self):
        p1 = Playlist.new(self.temp, "Foobar")
        p1.rename("Foo Quuxly")
        self.failUnlessEqual(p1.name, "Foo Quuxly")
        p1.delete()

    def test_rename_nothing(self):
        p1 = Playlist.new(self.temp, "Foobar")
        self.failUnlessRaises(ValueError, p1.rename, "")
        p1.delete()

    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()

    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()

    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_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()

    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_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_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_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_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_updating_aggregates_clear(s):
        pl = Playlist(s.temp, "playlist")
        pl.extend(NUMERIC_SONGS)
        s.failUnless(pl.get("~#length"))

        pl.clear()
        s.failIf(pl.get("~#length"))

    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_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_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_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_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)

    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])))
from tests import TestCase, mkdtemp
from quodlibet.formats._audio import AudioFile as Fakesong
from quodlibet.formats._audio import INTERN_NUM_DEFAULT, PEOPLE
from quodlibet.util.collection import Album, Playlist, avg, bayesian_average
from quodlibet.library.libraries import FileLibrary

config.RATINGS = config.HardCodedRatingsPrefs()

NUMERIC_SONGS = [
    Fakesong({
        "~filename": "fake1.mp3",
        "~#length": 4,
        "~#added": 5,
        "~#lastplayed": 1,
        "~#bitrate": 200,
        "date": "100",
        "~#rating": 0.1,
        "originaldate": "2004-01-01",
        "~#filesize": 101
    }),
    Fakesong({
        "~filename": "fake2.mp3",
        "~#length": 7,
        "~#added": 7,
        "~#lastplayed": 88,
        "~#bitrate": 220,
        "date": "99",
        "~#rating": 0.3,
        "originaldate": "2002-01-01",
        "~#filesize": 202
Пример #15
0
from quodlibet.formats._audio import AudioFile as Fakesong
from quodlibet.formats._audio import INTERN_NUM_DEFAULT, PEOPLE
from quodlibet.util.collection import Album, Playlist, avg, bayesian_average
from quodlibet.library.libraries import FileLibrary
from quodlibet.util import format_rating
from quodlibet.util.path import fsnative

config.RATINGS = config.HardCodedRatingsPrefs()

NUMERIC_SONGS = [
    Fakesong({
        "~filename": fsnative(u"fake1-\xf0.mp3"),
        "~#length": 4,
        "~#added": 5,
        "~#lastplayed": 1,
        "~#bitrate": 200,
        "date": "100",
        "~#rating": 0.1,
        "originaldate": "2004-01-01",
        "~#filesize": 101
    }),
    Fakesong({
        "~filename": fsnative(u"fake2.mp3"),
        "~#length": 7,
        "~#added": 7,
        "~#lastplayed": 88,
        "~#bitrate": 220,
        "date": "99",
        "~#rating": 0.3,
        "originaldate": "2002-01-01",
        "~#filesize": 202