def NamedTemporaryFile(*args, **kwargs): """Like tempfile.NamedTemporaryFile, but supports unicode paths on Py2+Windows """ if not PY3 and kwargs.get("dir", None) is None: kwargs["dir"] = gettempdir() return tempfile.NamedTemporaryFile(*args, **kwargs)
def get_thumbnail(path, boundary, ignore_temp=True): """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/ If ignore_temp then no thumbnail cache will be created for files in the default temporary directory. Can raise GLib.GError. Thread-safe. """ assert isinstance(path, fsnative) 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 ignore_temp and path.startswith(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 = fsn2uri(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", list(options.keys()), list(options.values())) try: os.chmod(thumb_path, 0o600) except OSError: pass return scale(thumb_pb, boundary)