def test_sanitize_py2_fixup(self):
        if PY3:
            return

        old = dict.__new__(AudioFile)
        dict.__init__(old, {
            b"foo": b"bar",
            u"öäü": b"bla",
            "~#num": u"1",
            "~#num2": u"1.25",
            "~#num3": u"bla",
            "~filename": u"text",
            "~mountpoint": b"bytes",
            "~somethingdifferent": b"hello",
        })

        fixed = {
            b"foo": u"bar",
            u"öäü": u"bla",
            "~#num": 1,
            "~#num2": 1.25,
            "~#num3": 0,
            "~filename": fsnative(u"text"),
            "~mountpoint": fsnative(u"bytes"),
            "~somethingdifferent": u"hello",
        }

        data = dump_audio_files([old])
        new = load_audio_files(data)
        assert dict(new[0]) == fixed
        for v1, v2 in zip(sorted(new[0].values()), sorted(fixed.values())):
            assert type(v1) is type(v2)
Пример #2
0
def init_test_environ():
    """This needs to be called before any test can be run.

    Before exiting the process call exit_test_environ() to clean up
    any resources created.
    """

    global _TEMP_DIR, _BUS_INFO, _VDISPLAY, _faulthandler_fobj

    # create a user dir in /tmp and set env vars
    _TEMP_DIR = tempfile.mkdtemp(prefix=fsnative(u"QL-TEST-"))

    # needed for dbus/dconf
    runtime_dir = tempfile.mkdtemp(prefix=fsnative(u"RUNTIME-"), dir=_TEMP_DIR)
    os.chmod(runtime_dir, 0o700)
    environ["XDG_RUNTIME_DIR"] = runtime_dir

    # force the old cache dir so that GStreamer can re-use the GstRegistry
    # cache file
    environ["XDG_CACHE_HOME"] = xdg_get_cache_home()
    # GStreamer will update the cache if the environment has changed
    # (in Gst.init()). Since it takes 0.5s here and doesn't add much,
    # disable it. If the registry cache is missing it will be created
    # despite this setting.
    environ["GST_REGISTRY_UPDATE"] = fsnative(u"no")

    # set HOME and remove all XDG vars that default to it if not set
    home_dir = tempfile.mkdtemp(prefix=fsnative(u"HOME-"), dir=_TEMP_DIR)
    environ["HOME"] = home_dir

    # set to new default
    environ.pop("XDG_DATA_HOME", None)

    if xvfbwrapper is not None:
        _VDISPLAY = xvfbwrapper.Xvfb()
        _VDISPLAY.start()

    _BUS_INFO = None
    if os.name != "nt" and "DBUS_SESSION_BUS_ADDRESS" in environ:
        _BUS_INFO = dbus_launch_user()
        environ.update(_BUS_INFO)

    quodlibet.init(no_translations=True, no_excepthook=True)
    quodlibet.app.name = "QL Tests"

    # to get around pytest silencing
    _faulthandler_fobj = os.fdopen(os.dup(sys.__stderr__.fileno()), "w")
    faulthandler.enable(_faulthandler_fobj)

    # try to make things the same in case a different locale is active.
    # LANG for gettext, setlocale for number formatting etc.
    # Note: setlocale has to be called after Gtk.init()
    try:
        if os.name != "nt":
            environ["LANG"] = locale.setlocale(locale.LC_ALL, "en_US.UTF-8")
        else:
            environ["LANG"] = "en_US.utf8"
            locale.setlocale(locale.LC_ALL, "english")
    except locale.Error:
        pass
Пример #3
0
    def test_types(self):
        from quodlibet.util.path import normalize_path

        assert isinstance(normalize_path(fsnative(u"foo"), False), fsnative)
        assert isinstance(normalize_path("foo", False), fsnative)
        assert isinstance(normalize_path(fsnative(u"foo"), True), fsnative)
        assert isinstance(normalize_path("foo", True), fsnative)
Пример #4
0
    def test_selection_set_songs(self):
        song = AudioFile()
        song["~filename"] = fsnative(u"foo")
        sel = MockSelData()
        qltk.selection_set_songs(sel, [song])
        assert sel.data == fsn2bytes(fsnative(u"foo"), "utf-8")

        assert qltk.selection_get_filenames(sel) == [fsnative(u"foo")]
Пример #5
0
 def test_disctrack(self):
     pat = TagsFromPattern('<discnumber><tracknumber>. <title>')
     self.assertEquals(pat.match_path(fsnative(u'101. T1.ogg')),
         dict(discnumber='1', tracknumber='01', title='T1'))
     self.assertEquals(pat.match_path(fsnative(u'1318. T18.ogg')),
         dict(discnumber='13', tracknumber='18', title='T18'))
     self.assertEquals(pat.match_path(fsnative(u'24. T4.ogg')),
         dict(discnumber='2', tracknumber='4', title='T4'))
Пример #6
0
    def sanitize(self, filename=None):
        """Fill in metadata defaults. Find ~mountpoint, ~#mtime, ~#filesize
        and ~#added. Check for null bytes in tags.

        Does not raise.
        """

        # Replace nulls with newlines, trimming zero-length segments
        for key, val in listitems(self):
            self[key] = val
            if isinstance(val, string_types) and '\0' in val:
                self[key] = '\n'.join(filter(lambda s: s, val.split('\0')))
            # Remove unnecessary defaults
            if key in NUMERIC_ZERO_DEFAULT and val == 0:
                del self[key]

        if filename:
            self["~filename"] = filename
        elif "~filename" not in self:
            raise ValueError("Unknown filename!")

        assert isinstance(self["~filename"], fsnative)

        if self.is_file:
            self["~filename"] = normalize_path(
                self["~filename"], canonicalise=True)
            # Find mount point (terminating at "/" if necessary)
            head = self["~filename"]
            while "~mountpoint" not in self:
                head, tail = os.path.split(head)
                # Prevent infinite loop without a fully-qualified filename
                # (the unit tests use these).
                head = head or fsnative(u"/")
                if ismount(head):
                    self["~mountpoint"] = head
        else:
            self["~mountpoint"] = fsnative(u"/")

        # Fill in necessary values.
        self.setdefault("~#added", int(time.time()))

        # For efficiency, do a single stat here. See Issue 504
        try:
            stat = os.stat(self['~filename'])
            self["~#mtime"] = stat.st_mtime
            self["~#filesize"] = stat.st_size

            # Issue 342. This is a horrible approximation (due to headers) but
            # on FLACs, the most common case, this should be close enough
            if "~#bitrate" not in self:
                try:
                    # kbps = bytes * 8 / seconds / 1000
                    self["~#bitrate"] = int(stat.st_size /
                                            (self["~#length"] * (1000 / 8)))
                except (KeyError, ZeroDivisionError):
                    pass
        except OSError:
            self["~#mtime"] = 0
Пример #7
0
 def test_uri2fsn(self):
     if os.name != "nt":
         path = uri2fsn("file:///home/piman/cr%21azy")
         self.assertTrue(isinstance(path, fsnative))
         self.assertEqual(path, fsnative(u"/home/piman/cr!azy"))
     else:
         path = uri2fsn("file:///C:/foo")
         self.assertTrue(isinstance(path, fsnative))
         self.assertEqual(path, fsnative(u"C:\\foo"))
Пример #8
0
 def test_sort_albums(self):
     # Make sure we have more than one album, one having a null date
     f = AF({"~filename": fsnative(u"/1"), "album": "one"})
     f2 = AF({"~filename": fsnative(u"/2"), "album": "one"})
     f3 = AF({"~filename": fsnative(u"/3"), "album": "two", "date": "2009"})
     f4 = AF({"~filename": fsnative(u"/4")})
     albums, count = _sort_albums([f, f2, f3, f4])
     self.failUnlessEqual(count, 1)
     self.failUnlessEqual(len(albums), 2)
Пример #9
0
def atomic_save(filename, mode):
    """Try to replace the content of a file in the safest way possible.

    A temporary file will be created in the same directory where the
    replacement data can be written into.
    After writing is done the data will be flushed to disk and the original
    file replaced atomically.

    In case of an error this raises IOError and OSError and the original file
    will be untouched. In case the computer crashes or any other
    non-recoverable error happens the temporary file will be left behind and
    has to be deleted manually.

    with atomic_save("config.cfg", "wb") as f:
        f.write(data)
    """

    assert isinstance(filename, fsnative)

    dir_ = os.path.dirname(filename)
    basename = os.path.basename(filename)
    fileobj = tempfile.NamedTemporaryFile(
        mode=mode, dir=dir_,
        prefix=basename + fsnative(u"_"), suffix=fsnative(u".tmp"),
        delete=False)

    try:
        yield fileobj

        fileobj.flush()
        fileno = fileobj.fileno()

        if os.name != "nt" and hasattr(fcntl, "F_FULLFSYNC"):
            # on OSX fsync doesn't sync all the way..
            # https://lists.apple.com/archives/darwin-dev/2005/Feb/msg00072.html
            # https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/fsync.2.html
            fcntl.fcntl(fileno, fcntl.F_FULLFSYNC)
        else:
            # on linux fsync goes all the way by default
            # http://linux.die.net/man/2/fsync
            os.fsync(fileno)

        fileobj.close()

        if os.name == "nt":
            _windows_rename(fileobj.name, filename)
        else:
            os.rename(fileobj.name, filename)
    except:
        try:
            os.unlink(fileobj.name)
        except OSError:
            pass
        raise
    finally:
        fileobj.close()
Пример #10
0
    def test_roundtrip(self):
        if os.name == "nt":
            paths = [u"C:\\öäü.txt"]
        else:
            paths = [u"/öäü.txt", u"/a/foo/bar", u"/a/b/foo/bar"]

        for source in paths:
            path = uri2fsn(fsn2uri(fsnative(source)))
            self.assertTrue(isinstance(path, fsnative))
            self.assertEqual(path, fsnative(source))
Пример #11
0
 def test_fsn2uri(self):
     if os.name != "nt":
         uri = fsn2uri(fsnative(u"/öäü.txt"))
         self.assertEqual(uri, u"file:///%C3%B6%C3%A4%C3%BC.txt")
     else:
         uri = fsn2uri(fsnative(u"C:\\öäü.txt"))
         self.assertEqual(
             uri, "file:///C:/%C3%B6%C3%A4%C3%BC.txt")
         self.assertEqual(
             fsn2uri(u"C:\\SomeDir\xe4"), "file:///C:/SomeDir%C3%A4")
Пример #12
0
    def test_conv(self):
        empty = fsnative(u"")

        v = self.c.filter(empty, fsnative(u"foobar baz"))
        self.failUnlessEqual(v, fsnative(u"foobar baz"))
        self.failUnless(isinstance(v, fsnative))

        v = self.c.filter(empty, fsnative(u"Foobar.BAZ"))
        self.failUnlessEqual(v, fsnative(u"foobar.baz"))
        self.failUnless(isinstance(v, fsnative))
Пример #13
0
    def test_types(self):
        v = strip_win32_incompat_from_path(fsnative(u""))
        self.assertTrue(isinstance(v, fsnative))
        v = strip_win32_incompat_from_path(fsnative(u"foo"))
        self.assertTrue(isinstance(v, fsnative))

        v = strip_win32_incompat_from_path(u"")
        self.assertTrue(isinstance(v, text_type))
        v = strip_win32_incompat_from_path(u"foo")
        self.assertTrue(isinstance(v, text_type))
Пример #14
0
    def test_ends_with_dots_or_spaces(self):
        empty = fsnative(u"")
        v = self.c.filter(empty, fsnative(u'foo. . '))
        self.failUnlessEqual(v, fsnative(u"foo. ._"))
        self.assertTrue(isinstance(v, fsnative))

        if os.name == "nt":
            self.failUnlessEqual(
                self.c.filter(empty, u'foo. \\bar .'), u"foo._\\bar _")
        else:
            self.failUnlessEqual(
                self.c.filter(empty, u'foo. /bar .'), "foo._/bar _")
Пример #15
0
def set_scan_dirs(dirs):
    """Saves a list of fs paths which should be scanned

    Args:
        list
    """

    assert all(isinstance(d, fsnative) for d in dirs)

    if is_windows():
        joined = fsnative(u":").join(dirs)
    else:
        joined = join_escape(dirs, fsnative(u":"))
    config.setbytes("settings", "scan", fsn2bytes(joined, "utf-8"))
Пример #16
0
 def test_main(self):
     self.assertEqual(decode_value("~#foo", 0.25), u"0.25")
     self.assertEqual(decode_value("~#foo", 4), u"4")
     self.assertEqual(decode_value("~#foo", "bar"), u"bar")
     self.assertTrue(isinstance(decode_value("~#foo", "bar"), text_type))
     path = fsnative(u"/foobar")
     self.assertEqual(decode_value("~filename", path), fsn2text(path))
Пример #17
0
def limit_path(path, ellipsis=True):
    """Reduces the filename length of all filenames in the given path
    to the common maximum length for current platform.

    While the limits are depended on the file system and more restrictions
    may apply, this covers the common case.
    """

    assert isinstance(path, fsnative)

    main, ext = os.path.splitext(path)
    parts = main.split(sep)
    for i, p in enumerate(parts):
        # Limit each path section to 255 (bytes on linux, chars on win).
        # http://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits
        limit = 255
        if i == len(parts) - 1:
            limit -= len(ext)

        if len(p) > limit:
            if ellipsis:
                p = p[:limit - 2] + fsnative(u"..")
            else:
                p = p[:limit]
        parts[i] = p

    return sep.join(parts) + ext
Пример #18
0
 def test_conv(self):
     empty = fsnative(u"")
     in_ = u"foo \u00c1 \u1234"
     out = u"foo _ _"
     v = self.c.filter(empty, in_)
     self.failUnlessEqual(v, out)
     self.failUnless(isinstance(v, text_type))
Пример #19
0
    def test_embedded_special_cover_words(self):
        """Tests that words incidentally containing embedded "special" words
        album keywords (e.g. cover, disc, back) don't trigger
        See Issue 818"""

        song = AudioFile({
            "~filename": fsnative(os.path.join(self.dir, u"asong.ogg")),
            "album": "foobar",
            "title": "Ode to Baz",
            "artist": "Q-Man",
        })
        data = [('back.jpg', False),
                ('discovery.jpg', False),
                ("Pharell - frontin'.jpg", False),
                ('nickelback - Curb.jpg', False),
                ('foobar.jpg', True),
                ('folder.jpg', True),  # Though this order is debatable
                ('Q-Man - foobar.jpg', True),
                ('Q-man - foobar (cover).jpg', True)]
        for fn, should_find in data:
            f = self.add_file(fn)
            cover = self._find_cover(song)
            if cover:
                actual = os.path.abspath(cover.name)
                assert path_equal(
                    actual, f, "\"%s\" should trump \"%s\"" % (f, actual))
            else:
                self.failIf(should_find, msg="Couldn't find %s for %s" %
                                             (f, song("~filename")))
Пример #20
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")
        with self.wrap("playlist", lib) as pl:
            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)

            lib.destroy()
Пример #21
0
 def test_drag_data_get(self):
     b = self.bar
     song = AudioFile()
     song["~filename"] = fsnative(u"foo")
     sel = MockSelData()
     qltk.selection_set_songs(sel, [song])
     b._drag_data_get(None, None, sel, DND_QL, None)
Пример #22
0
 def test_conv(self):
     empty = fsnative(u"")
     test = u"\u00c1 test"
     out = u"A test"
     v = self.c.filter(empty, test)
     self.failUnlessEqual(v, out)
     self.failUnless(isinstance(v, text_type))
Пример #23
0
 def test_rename_to_existing(self):
     quux.rename(quux("~basename"))
     if os.name != "nt":
         self.failUnlessRaises(
             ValueError, quux.rename, fsnative(u"/dev/null"))
     self.failUnlessRaises(ValueError, quux.rename,
                           get_data_path("silence-44-s.ogg"))
Пример #24
0
 def test_tag_text_types(self):
     for t in format_types:
         i = AudioFile.__new__(t)
         i["~filename"] = fsnative(u"foo")
         for tag in TAGS.values():
             name = tag.name
             # brute force
             variants = [
                 name, "~" + name, name + "sort", "~" + name + "sort",
                 name + ":role", "~" + name + ":role",
                 "~" + name + "sort:role", name + "sort:role",
             ]
             for name in variants:
                 if name in FILESYSTEM_TAGS:
                     assert isinstance(i(name, fsnative()), fsnative)
                 else:
                     assert isinstance(i(name), text_type)
Пример #25
0
def unexpand(filename):
    """Replace the user's home directory with ~ or %USERPROFILE%, if it
    appears at the start of the path name.

    Args:
        filename (fsnative): The file path
    Returns:
        fsnative: The path with the home directory replaced
    """

    sub = (os.name == "nt" and fsnative(u"%USERPROFILE%")) or fsnative(u"~")
    home = expanduser("~")
    if filename == home:
        return sub
    elif filename.startswith(home + os.path.sep):
        filename = filename.replace(home, sub, 1)
    return filename
Пример #26
0
    def setUp(self):
        config.init()
        self.s1 = AudioFile(
            {"album": "I Hate: Tests", "artist": "piman", "title": "Quuxly",
             "version": "cake mix", "~filename": fsnative(u"/dir1/foobar.ogg"),
             "~#length": 224, "~#skipcount": 13, "~#playcount": 24,
             "date": "2007-05-24"})
        self.s2 = AudioFile(
            {"album": "Foo the Bar", "artist": "mu", "title": "Rockin' Out",
             "~filename": fsnative(u"/dir2/something.mp3"),
             "tracknumber": "12/15"})

        self.s3 = AudioFile(
            {"artist": "piman\nmu",
             "~filename": fsnative(u"/test/\xf6\xe4\xfc/fo\xfc.ogg")})
        self.s4 = AudioFile({"title": u"Ångström", "utf8": "Ångström"})
        self.s5 = AudioFile({"title": "oh&blahhh", "artist": "!ohno"})
Пример #27
0
    def test_currentsong_length(self):
        app.player.go_to(AudioFile({
            "~filename": fsnative(),
            "~#length": 12.25,
        }))

        response = self._cmd(b"currentsong\n")
        assert b"Time: 12\n" in response
Пример #28
0
 def setUp(self):
     config.RATINGS = config.HardCodedRatingsPrefs()
     self.failUnlessEqual(config.RATINGS.number, NUM_RATINGS)
     self.library = SongLibrary()
     self.library.librarian = SongLibrarian()
     self.af = AudioFile({"~filename": fsnative(u"/foo"), "~#rating": 1.0})
     self.af.sanitize()
     self.rmi = RatingsMenuItem([self.af], self.library)
Пример #29
0
def unexpand(filename):
    """Replace the user's home directory with ~ or %USERPROFILE%, if it
    appears at the start of the path name.

    Args:
        filename (fsnative): The file path
    Returns:
        fsnative: The path with the home directory replaced
    """

    sub = (os.name == "nt" and fsnative(u"%USERPROFILE%")) or fsnative(u"~")
    home = os.path.normcase(get_home_dir()).rstrip(os.path.sep)
    norm = os.path.normcase(filename)
    if norm == home:
        return sub
    elif norm.startswith(home + os.path.sep):
        filename = sub + filename[len(home):]
    return filename
Пример #30
0
    def test_sanitize_py2_normal(self):
        if PY3:
            return

        af = AudioFile({
            b"foo": u"bar",
            u"öäü": u"bla",
            "~#num": 1,
            "~#num2": long(2),
            "~#num3": 1.25,
            "~filename": fsnative(u"filename"),
            "~mountpoint": fsnative(u"mount"),
            "~somethingdifferent": u"hello",
        })

        data = dump_audio_files([af])
        new = load_audio_files(data)
        assert dict(new[0]) == dict(af)
Пример #31
0
    def test_write(self):
        with self.wrap("playlist") as pl:
            pl.extend(NUMERIC_SONGS)
            pl.extend([fsnative(u"xf0xf0")])
            pl.write()

            with open(pl.path, "rb") as h:
                self.assertEqual(len(h.read().splitlines()),
                                 len(NUMERIC_SONGS) + 1)
Пример #32
0
    def test_currentsong_length(self):
        app.player.go_to(
            AudioFile({
                "~filename": fsnative(),
                "~#length": 12.25,
            }))

        response = self._cmd(b"currentsong\n")
        assert b"Time: 12\n" in response
Пример #33
0
 def test_lyric_filename(self):
     song = AudioFile()
     song["~filename"] = fsnative(u"filename")
     self.assertTrue(isinstance(song.lyric_filename, fsnative))
     song["title"] = u"Title"
     song["artist"] = u"Artist"
     self.assertTrue(isinstance(song.lyric_filename, fsnative))
     song["lyricist"] = u"Lyricist"
     self.assertTrue(isinstance(song.lyric_filename, fsnative))
Пример #34
0
    def __init__(self, target, num):
        super(Song, self).__init__()

        self["title"] = "title_%d" % (num + 1)
        self["artist"] = "artist"
        self["album"] = "album"
        self["labelid"] = self["album"]
        self["~filename"] = \
            fsnative(os.path.join(target, self["title"] + ".mp3"))
Пример #35
0
    def test_rename_to_existing(self):
        self.quux.rename(self.quux("~filename"))
        if os.name != "nt":
            self.failUnlessRaises(ValueError, self.quux.rename,
                                  fsnative(u"/dev/null"))

        with temp_filename() as new_file:
            with self.assertRaises(ValueError):
                self.quux.rename(new_file)
Пример #36
0
 def setUp(self):
     config.init()
     player = NullPlayer()
     song = AudioFile()
     song.bookmarks = [(10, "bla")]
     song.sanitize(fsnative(u"/"))
     player.song = song
     self.player = player
     self.library = SongLibrary()
Пример #37
0
    def test_write(self):
        with self.wrap("playlist") as pl:
            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)
Пример #38
0
    def sanitize(self, filename=None):
        """Fill in metadata defaults. Find ~mountpoint, ~#mtime, ~#filesize
        and ~#added. Check for null bytes in tags.

        Does not raise.
        """

        # Replace nulls with newlines, trimming zero-length segments
        for key, val in listitems(self):
            if isinstance(val, string_types) and '\0' in val:
                self[key] = '\n'.join(filter(lambda s: s, val.split('\0')))
            # Remove unnecessary defaults
            if key in NUMERIC_ZERO_DEFAULT and val == 0:
                del self[key]

        if filename:
            self["~filename"] = filename
        elif "~filename" not in self:
            raise ValueError("Unknown filename!")

        assert isinstance(self["~filename"], fsnative)

        if self.is_file:
            self["~filename"] = normalize_path(self["~filename"],
                                               canonicalise=True)
            # Find mount point (terminating at "/" if necessary)
            head = self["~filename"]
            while "~mountpoint" not in self:
                head, tail = os.path.split(head)
                # Prevent infinite loop without a fully-qualified filename
                # (the unit tests use these).
                head = head or "/"
                if os.path.ismount(head):
                    self["~mountpoint"] = head
        else:
            self["~mountpoint"] = fsnative(u"/")

        # Fill in necessary values.
        self.setdefault("~#added", int(time.time()))

        # For efficiency, do a single stat here. See Issue 504
        try:
            stat = os.stat(self['~filename'])
            self["~#mtime"] = stat.st_mtime
            self["~#filesize"] = stat.st_size

            # Issue 342. This is a horrible approximation (due to headers) but
            # on FLACs, the most common case, this should be close enough
            if "~#bitrate" not in self:
                try:
                    # kbps = bytes * 8 / seconds / 1000
                    self["~#bitrate"] = int(stat.st_size / (self["~#length"] *
                                                            (1000 / 8)))
                except (KeyError, ZeroDivisionError):
                    pass
        except OSError:
            self["~#mtime"] = 0
Пример #39
0
    def setUp(self):
        config.init()
        self.library = SongLibrary()
        backend = quodlibet.player.init_backend("nullbe")
        self.device = backend.init(self.library)

        self.songs = [AudioFile({"title": x}) for x in
                      ["song1", "song2", "song3"]]
        for song in self.songs:
            song.sanitize(fsnative(unicode(song["title"])))
Пример #40
0
 def test_ext_case_preservation(s):
     x = AudioFile({'~filename': fsnative(u'/tmp/Xx.Flac'), 'title': 'Xx'})
     # If pattern has a particular ext, preserve case of ext
     p1 = s._create('<~basename>')
     s.assertEquals(p1.format(x), 'Xx.Flac')
     p2 = s._create('<title>.FLAC')
     s.assertEquals(p2.format(x), 'Xx.FLAC')
     # If pattern doesn't have a particular ext, lowercase ext
     p3 = s._create('<title>')
     s.assertEquals(p3.format(x), 'Xx.flac')
Пример #41
0
 def __init__(self, num, album=None):
     super(AlbumSong, self).__init__()
     self["~filename"] = fsnative(u"file_%d.mp3" % (num + 1))
     self["title"] = "Song %d" % (num + 1)
     self["artist"] = "Fakeman"
     if album is None:
         self["album"] = "Album %d" % (num % 3 + 1)
     else:
         self["album"] = album
     self["labelid"] = self["album"]
Пример #42
0
    def test_rename(self):
        old_fn = quux("~basename")
        new_fn = fsnative(u"anothersong.mp3")
        dir = os.path.dirname(get_data_path(""))
        self.failUnless(quux.exists())
        quux.rename(new_fn)
        self.failIf(os.path.exists(dir + old_fn),
                    "%s already exists" % (dir + old_fn))
        self.failUnless(quux.exists())
        quux.rename(old_fn)
        self.failIf(os.path.exists(dir + new_fn))
        self.failUnless(quux.exists())

        # move out of parent dir and back
        quux.rename(fsnative(u"/tmp/more_test_data"))
        self.failIf(os.path.exists(dir + old_fn))
        self.failUnless(quux.exists())
        quux.rename(dir + old_fn)
        self.failUnless(quux.exists())
Пример #43
0
    def lyric_filename(self):
        """Returns the (potential) lyrics filename for this file"""

        filename = self.comma("title").replace(u'/', u'')[:128] + u'.lyric'
        sub_dir = ((self.comma("lyricist")
                    or self.comma("artist")).replace(u'/', u'')[:128])

        if os.name == "nt":
            # this was added at a later point. only use escape_filename here
            # to keep the linux case the same as before
            filename = escape_filename(filename)
            sub_dir = escape_filename(sub_dir)
        else:
            filename = fsnative(filename)
            sub_dir = fsnative(sub_dir)

        path = os.path.join(expanduser(fsnative(u"~/.lyrics")), sub_dir,
                            filename)
        return path
Пример #44
0
def _print_playing(app, fstring="<artist~album~tracknumber~title>"):
    from quodlibet.formats import AudioFile
    from quodlibet.pattern import Pattern

    song = app.player.info
    if song is None:
        song = AudioFile({"~filename": fsnative(u"/")})
        song.sanitize()

    return Pattern(fstring).format(song) + "\n"
Пример #45
0
def escape_filename(s):
    """Escape a string in a manner suitable for a filename.

    Takes unicode or str and returns a fsnative path.
    """

    if isinstance(s, unicode):
        s = s.encode("utf-8")

    return fsnative(urllib.quote(s, safe="").decode("utf-8"))
Пример #46
0
    def test_main(self):
        v = fsnative(u"foo")
        self.assertTrue(isinstance(v, fsnative))

        v2 = glib2fsn(fsn2glib(v))
        self.assertTrue(isinstance(v2, fsnative))
        self.assertEqual(v, v2)

        v3 = bytes2fsn(fsn2bytes(v, "utf-8"), "utf-8")
        self.assertTrue(isinstance(v3, fsnative))
        self.assertEqual(v, v3)
Пример #47
0
def main(argv=None):
    if argv is None:
        argv = sys_argv

    import quodlibet

    config_file = os.path.join(quodlibet.get_user_dir(), "config")
    quodlibet.init(config_file=config_file)

    from quodlibet.qltk import add_signal_watch
    add_signal_watch(app.quit)

    opts = util.OptionParser("Ex Falso", const.VERSION,
                             _("an audio tag editor"), "[%s]" % _("directory"))

    argv.append(os.path.abspath(fsnative(u".")))
    opts, args = opts.parse(argv[1:])
    args[0] = os.path.realpath(args[0])

    app.name = "Ex Falso"
    app.description = _("Audio metadata editor")
    app.id = "exfalso"
    app.process_name = "exfalso"
    quodlibet.set_application_info(app)

    import quodlibet.library
    import quodlibet.player
    app.library = quodlibet.library.init()
    app.player = quodlibet.player.init_player("nullbe", app.librarian)
    from quodlibet.qltk.songlist import PlaylistModel
    app.player.setup(PlaylistModel(), None, 0)
    pm = quodlibet.init_plugins()
    pm.rescan()

    from quodlibet.qltk.exfalsowindow import ExFalsoWindow
    dir_ = args[0]
    app.window = ExFalsoWindow(app.library, dir_)
    app.window.init_plugins()

    from quodlibet.util.cover import CoverManager
    app.cover_manager = CoverManager()
    app.cover_manager.init_plugins()

    from quodlibet import session
    session_client = session.init(app)

    quodlibet.enable_periodic_save(save_library=False)
    quodlibet.run(app.window)
    quodlibet.finish_first_session("exfalso")
    config.save()

    session_client.close()

    util.print_d("Finished shutdown.")
Пример #48
0
 def test_sanitize(self):
     q = AudioFile(quux)
     b = AudioFile(bar_1_1)
     q.sanitize()
     b.pop('~filename')
     self.failUnlessRaises(ValueError, b.sanitize)
     n = AudioFile({"artist": u"foo\0bar", "title": u"baz\0",
                    "~filename": fsnative(u"whatever")})
     n.sanitize()
     self.failUnlessEqual(n["artist"], "foo\nbar")
     self.failUnlessEqual(n["title"], "baz")
Пример #49
0
    def setUp(self):
        config.init()
        self.s1 = AudioFile(
            {"album": u"I Hate: Tests", "artist": u"piman", "title": u"Quuxly",
             "version": u"cake mix",
             "~filename": fsnative(u"/dir1/foobar.ogg"),
             "~#length": 224, "~#skipcount": 13, "~#playcount": 24,
             "date": u"2007-05-24"})
        self.s2 = AudioFile(
            {"album": u"Foo the Bar", "artist": u"mu", "title": u"Rockin' Out",
             "~filename": fsnative(u"/dir2/something.mp3"),
             "tracknumber": u"12/15"})

        self.s3 = AudioFile({
            "artist": u"piman\nmu",
            "~filename": fsnative(u"/test/\xf6\xe4\xfc/fo\xfc.ogg"),
            "~mountpoint": fsnative(u"/bla/\xf6\xe4\xfc/fo\xfc"),
        })
        self.s4 = AudioFile({"title": u"Ångström", "utf8": u"Ångström"})
        self.s5 = AudioFile({"title": u"oh&blahhh", "artist": u"!ohno"})
Пример #50
0
class TSongProperties(TestCase):
    af1 = AudioFile({"title": "woo"})
    af1.sanitize(fsnative(u"invalid"))
    af2 = AudioFile({"title": "bar", "album": "quux"})
    af2.sanitize(fsnative(u"alsoinvalid"))

    def setUp(self):
        SongProperties.plugins = DummyPlugins()
        config.init()
        self.library = SongLibrary()

    def test_onesong(self):
        self.window = SongProperties(self.library, [self.af1])

    def test_twosong(self):
        self.window = SongProperties(self.library, [self.af2, self.af1])

    def test_changed(self):
        self.test_twosong()
        self.window.hide()
        self.library.emit('changed', [self.af2])
        while Gtk.events_pending():
            Gtk.main_iteration()

    def test_removed(self):
        self.test_twosong()
        self.window.hide()
        self.library.emit('removed', [self.af2])
        while Gtk.events_pending():
            Gtk.main_iteration()

    def tearDown(self):
        try:
            self.window.destroy()
        except AttributeError:
            pass
        else:
            del (self.window)
        self.library.destroy()
        del (SongProperties.plugins)
        config.quit()
Пример #51
0
    def test_list(self):
        for key in bar_1_1.realkeys():
            self.failUnlessEqual(bar_1_1.list(key), [bar_1_1(key)])

        af = AudioFile({"~filename": fsnative(u"foo")})
        self.failUnlessEqual(af.list("artist"), [])
        self.failUnlessEqual(af.list("title"), [af("title")])
        self.failUnlessEqual(af.list("not a key"), [])

        self.failUnlessEqual(len(bar_2_1.list("artist")), 2)
        self.failUnlessEqual(bar_2_1.list("artist"),
                             bar_2_1["artist"].split("\n"))
Пример #52
0
    def test_write(self):
        with self.wrap("playlist") as pl:
            pl.extend(NUMERIC_SONGS)
            pl.extend([fsnative(u"xf0xf0")])
            pl.write()

            assert exists(pl.path), "File doesn't exist"
            root = ElementTree().parse(pl.path)
            assert root.tag == 'playlist'
            tracks = root.findall(".//track")
            assert len(tracks) == 4, "Hmm found %s" % tracks
            assert tracks[-1].find('location').text == "xf0xf0"
Пример #53
0
 def getline(key, value):
     song = AudioFile({"~filename": fsnative(u"/dev/null")})
     song.sanitize()
     song[key] = value
     lines = format_tags(song).splitlines()
     if not lines:
         return ""
     if len(lines) == 1:
         return lines[0]
     # hackery since title defaults to the filename..
     for l in lines:
         if not l.startswith("Title"):
             return l
Пример #54
0
def get_temp_cover_file(data):
    """Returns a file object or None"""

    try:
        # pass fsnative so that mkstemp() uses unicode on Windows
        fn = NamedTemporaryFile(prefix=fsnative(u"tmp"))
        fn.write(data)
        fn.flush()
        fn.seek(0, 0)
    except EnvironmentError:
        return
    else:
        return fn
Пример #55
0
def test_fsn2text():
    assert fsn2text(fsnative(u"foo")) == u"foo"
    with pytest.raises(TypeError):
        fsn2text(object())
    with pytest.raises(TypeError):
        fsn2text(notfsnative(u"foo"))

    for path in iternotfsn():
        with pytest.raises(TypeError):
            fsn2text(path)

    if os.name == "nt":
        assert fsn2text(u"\uD800\uDC01") == u"\U00010001"
Пример #56
0
 def test_tag_strs(self):
     for t in format_types:
         i = AudioFile.__new__(t)
         i["~filename"] = fsnative(u"foo")
         for tag in TAGS.values():
             name = tag.name
             # brute force
             variants = [
                 name,
                 "~" + name,
                 name + "sort",
                 "~" + name + "sort",
                 name + ":role",
                 "~" + name + ":role",
                 "~" + name + "sort:role",
                 name + "sort:role",
             ]
             for name in variants:
                 if name in FILESYSTEM_TAGS:
                     assert isinstance(i(name, fsnative()), fsnative)
                 else:
                     assert isinstance(i(name), str)
Пример #57
0
    def go_to(self, path_to_go):
        assert isinstance(path_to_go, fsnative)

        # The path should be normalized in normal situations.
        # On some systems and special environments (pipenv) there might be
        # a non-normalized path at least during tests, though.
        path_to_go = os.path.normpath(path_to_go)

        model = self.get_model()

        # Find the top level row which has the largest common
        # path with the path we want to go to
        roots = dict([(p, i) for (i, p) in model.iterrows(None)])
        head, tail = path_to_go, fsnative(u"")
        to_find = []
        while head and head not in roots:
            new_head, tail = os.path.split(head)
            # this can happen for invalid paths on Windows
            if head == new_head:
                break
            head = new_head
            to_find.append(tail)
        if head not in roots:
            return
        start_iter = roots[head]

        # expand until we find the right directory or the last valid one
        # and select/scroll to it
        def search(view, model, iter_, to_find):
            tree_path = model.get_path(iter_)

            # we are where we want, select and scroll
            if not to_find:
                view.set_cursor(tree_path)
                view.scroll_to_cell(tree_path)
                return

            # expand the row
            view.expand_row(tree_path, False)

            next_ = to_find.pop(-1)
            for sub_iter, path in model.iterrows(iter_):
                if os.path.basename(path) == next_:
                    search(view, model, sub_iter, to_find)
                    break
            else:
                # we haven't found the right sub folder, select the parent
                # and stop
                search(view, model, iter_, [])

        search(self, model, start_iter, to_find)
Пример #58
0
def test_fsnative():
    assert isinstance(fsnative(u"foo"), fsnative)
    fsntype = type(fsnative(u""))
    assert issubclass(fsntype, fsnative)
    with pytest.raises(TypeError):
        fsnative(b"")

    assert fsnative(u"\x00") == fsnative(u"\uFFFD")

    assert isinstance(fsnative(u"\x00"), fsnative)
    for inst in iternotfsn():
        assert not isinstance(inst, fsnative)
Пример #59
0
 def test_album_key(self):
     album_key_tests = [
         ({}, ((), (), '')),
         ({'album': 'foo'}, (('foo',), (), '')),
         ({'labelid': 'foo'}, ((), (), 'foo')),
         ({'musicbrainz_albumid': 'foo'}, ((), (), 'foo')),
         ({'album': 'foo', 'labelid': 'bar'}, (('foo',), (), 'bar')),
         ({'album': 'foo', 'labelid': 'bar', 'musicbrainz_albumid': 'quux'},
             (('foo',), (), 'bar')),
         ({'albumartist': 'a'}, ((), ('a',), '')),
         ]
     for tags, expected in album_key_tests:
         afile = AudioFile(**tags)
         afile.sanitize(fsnative(u'/dir/fn'))
         self.failUnlessEqual(afile.album_key, expected)
Пример #60
0
 def __init__(self,
              uri: str,
              track_id: int,
              client,
              favorite: bool = False):
     # Don't call super, it invokes __getitem__
     self["~uri"] = uri
     self.sanitize(fsnative(uri))
     self.client = client
     if not self.client:
         raise EnvironmentError("Must have a Soundcloud client")
     self["soundcloud_track_id"] = track_id
     self.favorite = favorite
     if self.favorite:
         self['~#rating'] = 1.0