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
파일: _audio.py 프로젝트: elfalem/quodlibet
    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
파일: path.py 프로젝트: elfalem/quodlibet
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
파일: path.py 프로젝트: elfalem/quodlibet
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
파일: test_api.py 프로젝트: lazka/senf
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
파일: test_api.py 프로젝트: lazka/senf
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