コード例 #1
0
ファイル: __init__.py プロジェクト: bossjones/quodlibet
def get_user_dir():
    """Place where QL saves its state, database, config etc."""

    if os.name == "nt":
        USERDIR = os.path.join(windows.get_appdate_dir(), "Quod Libet")
    else:
        USERDIR = os.path.join(os.path.expanduser("~"), ".quodlibet")

    if not PY2:
        USERDIR += "_py3"

    if 'QUODLIBET_USERDIR' in environ:
        USERDIR = environ['QUODLIBET_USERDIR']

    # XXX: Exec conf.py in this directory, used to override const globals
    # e.g. for setting USERDIR for the Windows portable version
    # Note: execfile doesn't handle unicode paths on windows, so encode.
    # (this doesn't use the old win api in case of str compared to os.*)
    _CONF_PATH = os.path.join(
        os.path.dirname(os.path.realpath(__file__)), "conf.py")
    if PY2:
        # FIXME: PY3PORT
        try:
            execfile(_CONF_PATH)
        except IOError:
            pass

    # XXX: users shouldn't assume the dir is there, but we currently do in
    # some places
    mkdir(USERDIR, 0o750)

    return USERDIR
コード例 #2
0
ファイル: __init__.py プロジェクト: Konzertheld/quodlibet
def init(icon=None, proc_title=None, name=None):
    global quodlibet

    print_d("Entering quodlibet.init")

    _gtk_init()
    _gtk_icons_init(get_image_dir(), icon)
    _gst_init()
    _dbus_init()
    _init_debug()

    from gi.repository import GLib

    if proc_title:
        GLib.set_prgname(proc_title)
        set_process_title(proc_title)
        # Issue 736 - set after main loop has started (gtk seems to reset it)
        GLib.idle_add(set_process_title, proc_title)

    if name:
        GLib.set_application_name(name)

    mkdir(get_user_dir(), 0750)

    print_d("Finished initialization.")
コード例 #3
0
ファイル: _main.py プロジェクト: zsau/quodlibet
def get_user_dir():
    """Place where QL saves its state, database, config etc."""

    if os.name == "nt":
        USERDIR = os.path.join(windows.get_appdata_dir(), "Quod Libet")
    elif is_osx():
        USERDIR = os.path.join(os.path.expanduser("~"), ".quodlibet")
    else:
        USERDIR = os.path.join(xdg_get_config_home(), "quodlibet")

        if not os.path.exists(USERDIR):
            tmp = os.path.join(os.path.expanduser("~"), ".quodlibet")
            if os.path.exists(tmp):
                USERDIR = tmp

    if 'QUODLIBET_USERDIR' in environ:
        USERDIR = environ['QUODLIBET_USERDIR']

    if build.BUILD_TYPE == u"windows-portable":
        USERDIR = os.path.normpath(os.path.join(
            os.path.dirname(path2fsn(sys.executable)), "..", "..", "config"))

    # XXX: users shouldn't assume the dir is there, but we currently do in
    # some places
    mkdir(USERDIR, 0o750)

    return USERDIR
コード例 #4
0
ファイル: logdump.py プロジェクト: LudoBike/quodlibet
def dump_to_disk(dump_dir, exc_info):
    """Writes a new error log file into 'dump_dir'

    Args:
        dump_dir (path-like)
        exc_info (tuple): sys.exc_info() result tuple
    """

    try:
        mkdir(dump_dir)
    except EnvironmentError:
        print_exc()
        return

    time_ = time.localtime()
    dump_path = os.path.join(
        dump_dir, time.strftime("Dump_%Y%m%d_%H%M%S.txt", time_))

    header = format_dump_header(exc_info).encode("utf-8")
    log = format_dump_log().encode("utf-8")

    try:
        with open(dump_path, "wb") as dump:
            dump.write(header)
            dump.write(log)
    except EnvironmentError:
        print_exc()
コード例 #5
0
ファイル: config.py プロジェクト: ZDBioHazard/quodlibet
    def write(self, filename):
        """Write config to filename.

        Can raise EnvironmentError
        """

        assert isinstance(filename, fsnative)

        mkdir(os.path.dirname(filename))

        # temporary set the new version for saving
        if self._version is not None:
            self.add_section("__config__")
            self.set("__config__", "version", self._version)
        try:
            with atomic_save(filename, "wb") as fileobj:
                if PY2:
                    self._config.write(fileobj)
                else:
                    temp = StringIO()
                    self._config.write(temp)
                    data = temp.getvalue().encode("utf-8", "surrogateescape")
                    fileobj.write(data)
        finally:
            if self._loaded_version is not None:
                self.set("__config__", "version", self._loaded_version)
コード例 #6
0
    def setUp(self):
        # Testing locally is VERY dangerous without this...
        self.assertTrue(_TEMP_DIR in PLAYLISTS or os.name == "nt",
                        msg="Failing, don't want to delete %s" % PLAYLISTS)
        try:
            shutil.rmtree(PLAYLISTS)
        except OSError:
            pass

        mkdir(PLAYLISTS)

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

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

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

        PlaylistsBrowser.init(self.lib)

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

        mkdir(PLAYLISTS)

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

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

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

        PlaylistsBrowser.init(self.lib)

        self.bar = PlaylistsBrowser(self.lib)
        self.bar.connect('songs-selected', self._expected)
        self.bar._select_playlist(self.bar.playlists()[0])
        self.expected = None
コード例 #8
0
ファイル: test_util.py プロジェクト: ZDBioHazard/quodlibet
 def test_manydeep(self):
     self.failUnless(not os.path.isdir("nonext"))
     mkdir("nonext/test/test2/test3")
     try:
         self.failUnless(os.path.isdir("nonext/test/test2/test3"))
     finally:
         os.rmdir("nonext/test/test2/test3")
         os.rmdir("nonext/test/test2")
         os.rmdir("nonext/test")
         os.rmdir("nonext")
コード例 #9
0
ファイル: _main.py プロジェクト: zsau/quodlibet
def get_cache_dir():
    """The directory to store things into which can be deleted at any time"""

    if os.name == "nt" and build.BUILD_TYPE == u"windows-portable":
        # avoid writing things to the host system for the portable build
        path = os.path.join(get_user_dir(), "cache")
    else:
        path = os.path.join(xdg_get_cache_home(), "quodlibet")

    mkdir(path, 0o700)
    return path
コード例 #10
0
 def test_lyric_filename_search_builtin_default(self):
     """test built-in default"""
     with self.lyric_filename_test_setup(no_config=True) as ts:
         fp = os.path.join(ts.root, ts["artist"], ts["title"] + ".lyric")
         p = os.path.dirname(fp)
         mkdir(p)
         with io.open(fp, "w", encoding='utf-8') as f:
             f.write(u"")
         search = unquote(ts.lyric_filename)
         os.remove(fp)
         os.rmdir(p)
         self.assertEqual(search, fp)
コード例 #11
0
 def test_lyrics_from_file(self):
     with temp_filename() as filename:
         af = AudioFile(artist='Motörhead', title='this: again')
         af.sanitize(filename)
         lyrics = "blah!\nblasé 😬\n"
         lyrics_dir = os.path.dirname(af.lyric_filename)
         mkdir(lyrics_dir)
         with io.open(af.lyric_filename, "w", encoding='utf-8') as lf:
             lf.write(text_type(lyrics))
         self.failUnlessEqual(af("~lyrics").splitlines(),
                              lyrics.splitlines())
         os.remove(af.lyric_filename)
         os.rmdir(lyrics_dir)
コード例 #12
0
ファイル: debugwindow.py プロジェクト: ZDBioHazard/quodlibet
    def dump_to_disk(self, type_, value, traceback):
        """Writes the dump files to DUMDIR"""

        mkdir(self.DUMPDIR)

        header = format_dump_header(type_, value, traceback).encode("utf-8")
        log = format_dump_log().encode("utf-8")

        print(self.dump_path)
        with open(self.dump_path, "wb") as dump:
            with open(self.minidump_path, "wb") as minidump:
                minidump.write(header)
                dump.write(header)
            dump.write(log)
コード例 #13
0
ファイル: debugwindow.py プロジェクト: brunob/quodlibet
    def from_except(Kind, *args):
        mkdir(Kind.DUMPDIR)

        dump = os.path.join(
            Kind.DUMPDIR, time.strftime("Dump_%Y%m%d_%H%M%S.txt"))
        minidump = os.path.join(
            Kind.DUMPDIR, time.strftime("MiniDump_%Y%m%d_%H%M%S.txt"))

        full_args = list(args) + [dump, minidump]
        Kind.__dump(*full_args)
        # Don't get in a recursive exception handler loop.
        if not Kind.running:
            Kind.running = True
            Kind.instance = Kind(*full_args)
        return Kind.instance
コード例 #14
0
ファイル: _audio.py プロジェクト: elfalem/quodlibet
    def rename(self, newname):
        """Rename a file. Errors are not handled. This shouldn't be used
        directly; use library.rename instead."""

        if os.path.isabs(newname):
            mkdir(os.path.dirname(newname))
        else:
            newname = os.path.join(self('~dirname'), newname)

        if not os.path.exists(newname):
            shutil.move(self['~filename'], newname)
        elif normalize_path(newname, canonicalise=True) != self['~filename']:
            raise ValueError

        self.sanitize(newname)
コード例 #15
0
ファイル: test_util.py プロジェクト: rakuna/quodlibet
 def test_manydeep(self):
     self.failUnless(not os.path.isdir("nonext"))
     t = mkdtemp()
     path = os.path.join(t, "nonext", "test", "test2", "test3")
     mkdir(path)
     try:
         self.failUnless(os.path.isdir(path))
     finally:
         os.rmdir(path)
         path = os.path.dirname(path)
         os.rmdir(path)
         path = os.path.dirname(path)
         os.rmdir(path)
         path = os.path.dirname(path)
         os.rmdir(path)
         os.rmdir(t)
コード例 #16
0
ファイル: fifo.py プロジェクト: kriskielce88/xn--ls8h
    def _open(self, *args):
        from quodlibet import qltk

        self._id = None
        try:
            if not os.path.exists(self._path):
                mkdir(os.path.dirname(self._path))
                os.mkfifo(self._path, 0600)
            fifo = os.open(self._path, os.O_NONBLOCK)
            f = os.fdopen(fifo, "r", 4096)
            self._id = qltk.io_add_watch(
                f, GLib.PRIORITY_DEFAULT,
                GLib.IO_IN | GLib.IO_ERR | GLib.IO_HUP,
                self._process, *args)
        except (EnvironmentError, AttributeError):
            pass
コード例 #17
0
ファイル: test_util.py プロジェクト: Muges/quodlibet
 def test_manydeep(self):
     self.failUnless(not os.path.isdir("nonext"))
     t = mkdtemp()
     path = os.path.join(t, "nonext", "test", "test2", "test3")
     mkdir(path)
     try:
         self.failUnless(os.path.isdir(path))
     finally:
         os.rmdir(path)
         path = os.path.dirname(path)
         os.rmdir(path)
         path = os.path.dirname(path)
         os.rmdir(path)
         path = os.path.dirname(path)
         os.rmdir(path)
         os.rmdir(t)
コード例 #18
0
    def setUp(self):
        self.success = False
        # Testing locally is VERY dangerous without this...
        self.assertTrue(_TEMP_DIR in _DEFAULT_PLAYLIST_DIR or os.name == "nt",
                        msg="Failing, don't want to delete %s" %
                        _DEFAULT_PLAYLIST_DIR)
        try:
            shutil.rmtree(_DEFAULT_PLAYLIST_DIR)
        except OSError:
            pass

        mkdir(_DEFAULT_PLAYLIST_DIR)

        init_fake_app()

        self.lib = quodlibet.browsers.playlists.library = SongFileLibrary()
        self.lib.librarian = SongLibrarian()
        for af in self.ALL_SONGS:
            af.sanitize()
        self.lib.add(self.ALL_SONGS)

        self.big = pl = FileBackedPlaylist.new(_DEFAULT_PLAYLIST_DIR, "Big",
                                               self.lib, self.lib.playlists)
        pl.extend(SONGS)
        pl.write()

        self.small = pl = XSPFBackedPlaylist.new(_DEFAULT_PLAYLIST_DIR,
                                                 "Small", self.lib,
                                                 self.lib.playlists)
        pl.extend([self.ANOTHER_SONG])
        pl.write()

        PlaylistsBrowser.init(self.lib)

        self.bar = PlaylistsBrowser(self.lib, self.MockConfirmerAccepting)
        self.bar.connect('songs-selected', self._expected)
        self.bar._select_playlist(self.bar.playlists()[0])
        self.expected = None

        # Uses the declining confirmer.
        self.bar_decline = PlaylistsBrowser(self.lib,
                                            self.MockConfirmerDeclining)
        self.bar_decline.connect('songs-selected', self._expected_decline)
        self.bar_decline._select_playlist(self.bar_decline.playlists()[0])
        # Note that _do() uses self.expected, but _do() is not called by the
        # testcase for declining the prompt. Tests fail with a shared expected.
        self.expected_decline = None
コード例 #19
0
def dump_items(filename, items):
    """Pickle items to disk.

    Doesn't handle exceptions.
    """

    dirname = os.path.dirname(filename)
    mkdir(dirname)

    with atomic_save(filename, "wb") as fileobj:
        # While protocol 2 is usually faster it uses __setitem__
        # for unpickle and we override it to clear the sort cache.
        # This roundtrip makes it much slower, so we use protocol 1
        # unpickle numbers (py2.7):
        #   2: 0.66s / 2 + __set_item__: 1.18s / 1 + __set_item__: 0.72s
        # see: http://bugs.python.org/issue826897
        pickle.dump(items, fileobj, 1)
コード例 #20
0
ファイル: libraries.py プロジェクト: kriskielce88/xn--ls8h
def dump_items(filename, items):
    """Pickle items to disk.

    Doesn't handle exceptions.
    """

    dirname = os.path.dirname(filename)
    mkdir(dirname)

    with util.atomic_save(filename, ".tmp", "wb") as fileobj:
        # While protocol 2 is usually faster it uses __setitem__
        # for unpickle and we override it to clear the sort cache.
        # This roundtrip makes it much slower, so we use protocol 1
        # unpickle numbers (py2.7):
        #   2: 0.66s / 2 + __set_item__: 1.18s / 1 + __set_item__: 0.72s
        # see: http://bugs.python.org/issue826897
        pickle.dump(items, fileobj, 1)
コード例 #21
0
ファイル: libraries.py プロジェクト: neurowarin/quodlibet
    def save(self, filename=None):
        """Save the library to the given filename, or the default if `None`"""

        if filename is None:
            filename = self.filename

        print_d("Saving contents to %r." % filename, self)

        try:
            dirname = os.path.dirname(filename)
            mkdir(dirname)
            with atomic_save(filename, "wb") as fileobj:
                fileobj.write(dump_audio_files(self.get_content()))
                # unhandled SerializationError, shouldn't happen -> better
                # not replace the library file with nothing
        except EnvironmentError:
            print_w("Couldn't save library to path: %r" % filename)
        else:
            self.dirty = False
コード例 #22
0
    def open(self, ignore_lock=False):
        """Create the FIFO and listen to it.

        Raises:
            FIFOError in case another process is already using it.
        """
        from quodlibet import qltk

        mkdir(os.path.dirname(self._path))
        try:
            os.mkfifo(self._path, 0o600)
        except OSError:
            # maybe exists, we'll fail below otherwise
            pass

        try:
            fifo = os.open(self._path, os.O_NONBLOCK)
        except OSError:
            return

        while True:
            try:
                fcntl.flock(fifo, fcntl.LOCK_EX | fcntl.LOCK_NB)
            except InterruptedError:  # EINTR
                continue
            except BlockingIOError:  # EWOULDBLOCK
                if not ignore_lock:
                    raise FIFOError("fifo already locked")
            except OSError as e:
                print_d(f"fifo locking failed: {e!r}")
            break

        try:
            f = os.fdopen(fifo, "rb", 4096)
        except OSError as e:
            print_e(f"Couldn't open FIFO ({e!r})")
        else:
            self._source_id = qltk.io_add_watch(
                f,
                GLib.PRIORITY_DEFAULT,
                GLib.IO_IN | GLib.IO_ERR | GLib.IO_HUP,
                self._process,
            )
コード例 #23
0
 def test_lyric_filename_search_order_priority(self):
     """test custom lyrics order priority"""
     with self.lyric_filename_test_setup() as ts:
         root2 = os.path.join(get_home_dir(), ".lyrics") # built-in default
         fp2 = os.path.join(root2, ts["artist"] + " - " +
                                   ts["title"] + ".lyric")
         p2 = os.path.dirname(fp2)
         mkdir(p2)
         with io.open(fp2, "w", encoding='utf-8') as f:
             f.write(u"")
         fp = os.path.join(ts.root, ts["artist"] + " - " +
                                    ts["title"] + ".lyric")
         with io.open(fp, "w", encoding='utf-8') as f:
             f.write(u"")
         mkdir(p2)
         search = ts.lyric_filename
         os.remove(fp2)
         os.rmdir(p2)
         os.remove(fp)
         self.assertEqual(search, fp)
コード例 #24
0
 def test_lyric_filename_search_order_priority(self):
     """test custom lyrics order priority"""
     with self.lyric_filename_test_setup() as ts:
         root2 = os.path.join(get_home_dir(), ".lyrics")  # built-in default
         fp2 = os.path.join(root2,
                            ts["artist"] + " - " + ts["title"] + ".lyric")
         p2 = os.path.dirname(fp2)
         mkdir(p2)
         with io.open(fp2, "w", encoding='utf-8') as f:
             f.write(u"")
         fp = os.path.join(ts.root,
                           ts["artist"] + " - " + ts["title"] + ".lyric")
         with io.open(fp, "w", encoding='utf-8') as f:
             f.write(u"")
         mkdir(p2)
         search = ts.lyric_filename
         os.remove(fp2)
         os.rmdir(p2)
         os.remove(fp)
         self.assertEqual(search, fp)
コード例 #25
0
    def test_invalid_glob_path(self):
        config.set("albumart", "force_filename", str(True))
        config.set("albumart", "filename", "*.jpg")

        # Make a dir which contains an invalid glob
        path = os.path.join(self.full_path("[a-2]"), "cover.jpg")
        mkdir(os.path.dirname(path))
        f = self.add_file(path)

        # Change the song's path to contain the invalid glob
        old_song_path = self.song['~filename']
        new_song_path = os.path.join(os.path.dirname(path),
                                     os.path.basename(old_song_path))
        self.song['~filename'] = new_song_path

        # The glob in the dirname should be ignored, while the
        # glob in the filename/basename is honored
        assert path_equal(os.path.abspath(self._find_cover(self.song).name), f)

        self.song['~filename'] = old_song_path
コード例 #26
0
ファイル: config.py プロジェクト: ch1huizong/scode
    def write(self, filename):
        """Write config to filename.

        Can raise EnvironmentError
        """

        assert is_fsnative(filename)

        mkdir(os.path.dirname(filename))

        # temporary set the new version for saving
        if self._version is not None:
            self.add_section("__config__")
            self.set("__config__", "version", self._version)
        try:
            with atomic_save(filename, ".tmp", "wb") as fileobj:
                self._config.write(fileobj)
        finally:
            if self._loaded_version is not None:
                self.set("__config__", "version", self._loaded_version)
コード例 #27
0
ファイル: config.py プロジェクト: brunob/quodlibet
    def write(self, filename):
        """Write config to filename.

        Can raise EnvironmentError
        """

        assert is_fsnative(filename)

        mkdir(os.path.dirname(filename))

        # temporary set the new version for saving
        if self._version is not None:
            self.add_section("__config__")
            self.set("__config__", "version", self._version)
        try:
            with atomic_save(filename, ".tmp", "wb") as fileobj:
                self._config.write(fileobj)
        finally:
            if self._loaded_version is not None:
                self.set("__config__", "version", self._loaded_version)
コード例 #28
0
ファイル: fifo.py プロジェクト: SimonLarsen/quodlibet
    def _open(self, ignore_lock, *args):
        from quodlibet import qltk

        self._id = None
        mkdir(os.path.dirname(self._path))
        try:
            os.mkfifo(self._path, 0600)
        except OSError:
            # maybe exists, we'll fail below otherwise
            pass

        try:
            fifo = os.open(self._path, os.O_NONBLOCK)
        except OSError:
            return

        while True:
            try:
                fcntl.flock(fifo, fcntl.LOCK_EX | fcntl.LOCK_NB)
            except IOError as e:
                # EINTR on linux
                if e.errno == errno.EINTR:
                    continue
                if ignore_lock:
                    break
                # OSX doesn't support fifo locking, so check errno
                if e.errno == errno.EWOULDBLOCK:
                    raise FIFOError("fifo already locked")
                else:
                    print_d("fifo locking failed: %r" % e)
            break

        try:
            f = os.fdopen(fifo, "r", 4096)
        except OSError:
            pass

        self._id = qltk.io_add_watch(
            f, GLib.PRIORITY_DEFAULT,
            GLib.IO_IN | GLib.IO_ERR | GLib.IO_HUP,
            self._process, *args)
コード例 #29
0
    def test_lyric_filename_search_special_characters_across_path(self):
        """test '<' and/or '>' in name across path separator (not parsed
        (transparent to test))"""
        with self.lyric_filename_test_setup(no_config=True) as ts:
            # test '<' and '>' in name across path
            # (not parsed (transparent to test))
            ts['artist'] = "a < b"
            ts['title'] = "b > a"
            parts = [ts.root, ts["artist"], ts["title"] + ".lyric"]
            rpf = RootPathFile(ts.root, os.path.sep.join(parts))
            rootp = ts.root
            rmdirs = []
            # ensure valid dir existence
            for p in rpf.end.split(os.path.sep)[:-1]:
                rootp = os.path.sep.join([ts.root, p])
                if not RootPathFile(ts.root, rootp).valid:
                    rootp = os.path.sep.join([ts.root, escape_filename(p)])
                self.assertTrue(
                    RootPathFile(ts.root, rootp).valid,
                    "even escaped target dir part is not valid!")
                if not os.path.exists(rootp):
                    mkdir(rootp)
                    rmdirs.append(rootp)

            if not rpf.valid:
                rpf = RootPathFile(rpf.root, rpf.pathfile_escaped)

            with io.open(rpf.pathfile, "w", encoding='utf-8') as f:
                f.write(u"")
            # search for lyric file
            search = ts.lyric_filename
            # clean up test lyric file / path
            os.remove(rpf.pathfile)
            for p in rmdirs:
                os.rmdir(p)
            # test whether the 'found' file is the test lyric file
            fp = rpf.pathfile
            if is_windows():
                fp = fp.lower()  # account for 'os.path.normcase' santisatation
                search = search.lower()  # compensate for the above
            self.assertEqual(search, fp)
コード例 #30
0
def get_user_dir():
    """Place where QL saves its state, database, config etc."""

    if os.name == "nt":
        USERDIR = os.path.join(windows.get_appdate_dir(), "Quod Libet")
    else:
        USERDIR = os.path.join(os.path.expanduser("~"), ".quodlibet")

    if 'QUODLIBET_USERDIR' in environ:
        USERDIR = environ['QUODLIBET_USERDIR']

    if build.BUILD_TYPE == u"windows-portable":
        USERDIR = os.path.normpath(
            os.path.join(os.path.dirname(path2fsn(sys.executable)), "..", "..",
                         "config"))

    # XXX: users shouldn't assume the dir is there, but we currently do in
    # some places
    mkdir(USERDIR, 0o750)

    return USERDIR
コード例 #31
0
ファイル: test_util_cover.py プロジェクト: LudoBike/quodlibet
    def test_invalid_glob_path(self):
        config.set("albumart", "force_filename", str(True))
        config.set("albumart", "filename", "*.jpg")

        # Make a dir which contains an invalid glob
        path = os.path.join(self.full_path("[a-2]"), "cover.jpg")
        mkdir(os.path.dirname(path))
        f = self.add_file(path)

        # Change the song's path to contain the invalid glob
        old_song_path = self.song['~filename']
        new_song_path = os.path.join(os.path.dirname(path),
                                     os.path.basename(old_song_path))
        self.song['~filename'] = new_song_path

        # The glob in the dirname should be ignored, while the
        # glob in the filename/basename is honored
        assert path_equal(
            os.path.abspath(self._find_cover(self.song).name), f)

        self.song['~filename'] = old_song_path
コード例 #32
0
    def test_lyric_filename_search_special_characters_across_path(self):
        """test '<' and/or '>' in name across path separator (not parsed
        (transparent to test))"""
        with self.lyric_filename_test_setup(no_config=True) as ts:
            # test '<' and '>' in name across path
            # (not parsed (transparent to test))
            ts['artist'] = "a < b"
            ts['title'] = "b > a"
            parts = [ts.root, ts["artist"], ts["title"] + ".lyric"]
            rpf = RootPathFile(ts.root, os.path.sep.join(parts))
            rootp = ts.root
            rmdirs = []
            # ensure valid dir existence
            for p in rpf.end.split(os.path.sep)[:-1]:
                rootp = os.path.sep.join([ts.root, p])
                if not RootPathFile(ts.root, rootp).valid:
                    rootp = os.path.sep.join([ts.root, escape_filename(p)])
                self.assertTrue(RootPathFile(ts.root, rootp).valid,
                                "even escaped target dir part is not valid!")
                if not os.path.exists(rootp):
                    mkdir(rootp)
                    rmdirs.append(rootp)

            if not rpf.valid:
                rpf = RootPathFile(rpf.root, rpf.pathfile_escaped)

            with io.open(rpf.pathfile, "w", encoding='utf-8') as f:
                f.write(u"")
            # search for lyric file
            search = ts.lyric_filename
            # clean up test lyric file / path
            os.remove(rpf.pathfile)
            for p in rmdirs:
                os.rmdir(p)
            # test whether the 'found' file is the test lyric file
            fp = rpf.pathfile
            if is_windows():
                fp = fp.lower()  # account for 'os.path.normcase' santisatation
                search = search.lower()  # compensate for the above
            self.assertEqual(search, fp)
コード例 #33
0
    def _open(self, ignore_lock, *args):
        from quodlibet import qltk

        self._id = None
        mkdir(os.path.dirname(self._path))
        try:
            os.mkfifo(self._path, 0o600)
        except OSError:
            # maybe exists, we'll fail below otherwise
            pass

        try:
            fifo = os.open(self._path, os.O_NONBLOCK)
        except OSError:
            return

        while True:
            try:
                fcntl.flock(fifo, fcntl.LOCK_EX | fcntl.LOCK_NB)
            except IOError as e:
                # EINTR on linux
                if e.errno == errno.EINTR:
                    continue
                if ignore_lock:
                    break
                # OSX doesn't support fifo locking, so check errno
                if e.errno == errno.EWOULDBLOCK:
                    raise FIFOError("fifo already locked")
                else:
                    print_d("fifo locking failed: %r" % e)
            break

        try:
            f = os.fdopen(fifo, "r", 4096)
        except OSError:
            pass

        self._id = qltk.io_add_watch(f, GLib.PRIORITY_DEFAULT,
                                     GLib.IO_IN | GLib.IO_ERR | GLib.IO_HUP,
                                     self._process, *args)
コード例 #34
0
ファイル: __init__.py プロジェクト: gbtami/quodlibet
def get_user_dir():
    """Place where QL saves its state, database, config etc."""

    if os.name == "nt":
        USERDIR = os.path.join(windows.get_appdate_dir(), "Quod Libet")
    else:
        USERDIR = os.path.join(os.path.expanduser("~"), ".quodlibet")

    if not PY2:
        USERDIR += "_py3"

    if 'QUODLIBET_USERDIR' in environ:
        USERDIR = environ['QUODLIBET_USERDIR']

    if build.BUILD_TYPE == u"windows-portable":
        USERDIR = os.path.join(get_base_dir(), "..", "..", "..", "config")

    # XXX: users shouldn't assume the dir is there, but we currently do in
    # some places
    mkdir(USERDIR, 0o750)

    return USERDIR
コード例 #35
0
ファイル: libraries.py プロジェクト: rakuna/quodlibet
    def save(self, filename=None):
        """Save the library to the given filename, or the default if `None`"""

        if filename is None:
            filename = self.filename

        print_d("Saving contents to %r." % filename, self)

        try:
            dirname = os.path.dirname(filename)
            mkdir(dirname)
            with atomic_save(filename, "wb") as fileobj:
                fileobj.write(dump_audio_files(self.get_content()))
        except SerializationError:
            # Can happen when we try to pickle while the library is being
            # modified, like in the periodic 15min save.
            # Ignore, as it should try again later or on program exit.
            util.print_exc()
        except EnvironmentError:
            print_w("Couldn't save library to path: %r" % filename)
        else:
            self.dirty = False
コード例 #36
0
ファイル: libraries.py プロジェクト: LudoBike/quodlibet
    def save(self, filename=None):
        """Save the library to the given filename, or the default if `None`"""

        if filename is None:
            filename = self.filename

        print_d("Saving contents to %r." % filename, self)

        try:
            dirname = os.path.dirname(filename)
            mkdir(dirname)
            with atomic_save(filename, "wb") as fileobj:
                fileobj.write(dump_audio_files(self.get_content()))
        except SerializationError:
            # Can happen when we try to pickle while the library is being
            # modified, like in the periodic 15min save.
            # Ignore, as it should try again later or on program exit.
            util.print_exc()
        except EnvironmentError:
            print_w("Couldn't save library to path: %r" % filename)
        else:
            self.dirty = False
コード例 #37
0
ファイル: config.py プロジェクト: weblate/quodlibet
    def write(self, filename):
        """Write config to filename.

        Can raise EnvironmentError
        """

        assert isinstance(filename, fsnative)

        mkdir(os.path.dirname(filename))

        # temporary set the new version for saving
        if self._version is not None:
            self.add_section("__config__")
            self.set("__config__", "version", self._version)
        try:
            with atomic_save(filename, "wb") as fileobj:
                temp = StringIO()
                self._config.write(temp)
                data = temp.getvalue().encode("utf-8", "surrogateescape")
                fileobj.write(data)
        finally:
            if self._loaded_version is not None:
                self.set("__config__", "version", self._loaded_version)
コード例 #38
0
def get_user_dir():
    """Place where QL saves its state, database, config etc."""

    if os.name == "nt":
        USERDIR = os.path.join(windows.get_appdate_dir(), "Quod Libet")
    else:
        USERDIR = os.path.join(os.path.expanduser("~"), ".quodlibet")

    if not PY2:
        USERDIR += "_py3"

    if 'QUODLIBET_USERDIR' in environ:
        USERDIR = environ['QUODLIBET_USERDIR']

    # XXX: Exec conf.py in this directory, used to override const globals
    # e.g. for setting USERDIR for the Windows portable version
    # Note: execfile doesn't handle unicode paths on windows, so encode.
    # (this doesn't use the old win api in case of str compared to os.*)
    _CONF_PATH = os.path.join(
        os.path.dirname(os.path.realpath(__file__)), "conf.py")

    if PY2:
        locals_ = {}
        # FIXME: PY3PORT
        try:
            execfile(_CONF_PATH, globals(), locals_)
        except IOError:
            pass
        else:
            USERDIR = locals_["USERDIR"]

    # XXX: users shouldn't assume the dir is there, but we currently do in
    # some places
    mkdir(USERDIR, 0o750)

    return USERDIR
コード例 #39
0
def get_thumbnail(path, boundary):
    """Get a thumbnail pixbuf of an image at `path`.

    Will create/use a thumbnail in the user's thumbnail directory if possible.
    Follows the Free Desktop specification:

    http://specifications.freedesktop.org/thumbnail-spec/

    Can raise GLib.GError. Thread-safe.
    """

    width, height = boundary
    new_from_file_at_size = GdkPixbuf.Pixbuf.new_from_file_at_size

    # larger than thumbnails, load directly
    if width > ThumbSize.LARGEST or height > ThumbSize.LARGEST:
        return new_from_file_at_size(path, width, height)

    path_mtime = mtime(path)
    if path_mtime == 0:
        return new_from_file_at_size(path, width, height)

    # embedded thumbnails come from /tmp/
    # FIXME: move this to another layer
    if path.startswith(tempfile.gettempdir()):
        return new_from_file_at_size(path, width, height)

    thumb_path, thumb_size = get_cache_info(path, boundary)
    cache_dir = os.path.dirname(thumb_path)
    try:
        mkdir(cache_dir, 0o700)
    except OSError:
        return new_from_file_at_size(path, width, height)

    try:
        pb = new_from_file_at_size(thumb_path, width, height)
    except GLib.GError:
        # in case it fails to load, we recreate it
        pass
    else:
        meta_mtime = pb.get_option("tEXt::Thumb::MTime")
        if meta_mtime is not None:
            try:
                meta_mtime = int(meta_mtime)
            except ValueError:
                pass
            else:
                if meta_mtime == int(path_mtime):
                    return pb

    info, pw, ph = GdkPixbuf.Pixbuf.get_file_info(path)

    # Too small picture, no thumbnail needed
    if pw < thumb_size and ph < thumb_size:
        return new_from_file_at_size(path, width, height)

    thumb_pb = new_from_file_at_size(path, thumb_size, thumb_size)

    uri = "file://" + pathname2url(path)
    mime = info.get_mime_types()[0]
    options = {
        "tEXt::Thumb::Image::Width": str(pw),
        "tEXt::Thumb::Image::Height": str(ph),
        "tEXt::Thumb::URI": uri,
        "tEXt::Thumb::MTime": str(int(path_mtime)),
        "tEXt::Thumb::Size": str(os.path.getsize(path)),
        "tEXt::Thumb::Mimetype": mime,
        "tEXt::Software": "QuodLibet"
    }

    thumb_pb.savev(thumb_path, "png", options.keys(), options.values())
    try:
        os.chmod(thumb_path, 0o600)
    except OSError:
        pass

    return scale(thumb_pb, boundary)
コード例 #40
0
ファイル: test_util.py プロジェクト: Muges/quodlibet
 def test_exists(self):
     mkdir(".")
コード例 #41
0
ファイル: util.py プロジェクト: SimonLarsen/quodlibet
import quodlibet
from quodlibet import formats, qltk
from quodlibet.qltk.wlw import WaitLoadWindow
from quodlibet.qltk.getstring import GetStringDialog
from quodlibet.util import escape
from quodlibet.util.collection import Playlist
from quodlibet.util.path import mkdir, fsdecode, is_fsnative


# Directory for playlist files
from quodlibet.util.uri import URI

PLAYLISTS = os.path.join(quodlibet.get_user_dir(), "playlists")
assert is_fsnative(PLAYLISTS)
if not os.path.isdir(PLAYLISTS):
    mkdir(PLAYLISTS)


class ConfirmRemovePlaylistDialog(qltk.Message):
    def __init__(self, parent, playlist):
        title = _("Are you sure you want to delete the playlist '%s'?") % escape(playlist.name)
        description = _("All information about the selected playlist " "will be deleted and can not be restored.")

        super(ConfirmRemovePlaylistDialog, self).__init__(
            Gtk.MessageType.WARNING, parent, title, description, Gtk.ButtonsType.NONE
        )

        self.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_DELETE, Gtk.ResponseType.YES)


class GetPlaylistName(GetStringDialog):
コード例 #42
0
ファイル: util.py プロジェクト: thisfred/quodlibet
from gi.repository import Gtk
from quodlibet import formats, qltk
from quodlibet.qltk.wlw import WaitLoadWindow
from quodlibet.qltk.getstring import GetStringDialog
from quodlibet.util import escape
from quodlibet.util.collection import Playlist
from quodlibet.util.path import mkdir, fsdecode, is_fsnative
from quodlibet import const

# Directory for playlist files
from quodlibet.util.uri import URI

PLAYLISTS = os.path.join(const.USERDIR, "playlists")
assert is_fsnative(PLAYLISTS)
if not os.path.isdir(PLAYLISTS):
    mkdir(PLAYLISTS)


class ConfirmRemovePlaylistDialog(qltk.Message):
    def __init__(self, parent, playlist):
        title = (_("Are you sure you want to delete the playlist '%s'?") %
                 escape(playlist.name))
        description = (_("All information about the selected playlist "
                         "will be deleted and can not be restored."))

        super(ConfirmRemovePlaylistDialog,
              self).__init__(Gtk.MessageType.WARNING, parent, title,
                             description, Gtk.ButtonsType.NONE)

        self.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
                         Gtk.STOCK_DELETE, Gtk.ResponseType.YES)
コード例 #43
0
ファイル: test_util.py プロジェクト: ptitjes/quodlibet
 def test_exists(self):
     mkdir(".")