Пример #1
0
def save_container(container, path):
    temp = PersistentTemporaryFile(prefix=('_' if iswindows else '.'),
                                   suffix=os.path.splitext(path)[1],
                                   dir=os.path.dirname(path))
    if hasattr(os, 'fchmod'):
        # Ensure file permissions and owner information is preserved
        fno = temp.fileno()
        try:
            st = os.stat(path)
        except EnvironmentError as err:
            if err.errno != errno.ENOENT:
                raise
            # path may not exist if we are saving a copy, in which case we use
            # the metadata from the original book
            st = os.stat(container.path_to_ebook)
        os.fchmod(fno, st.st_mode)
        try:
            os.fchown(fno, st.st_uid, st.st_gid)
        except EnvironmentError as err:
            if err.errno != errno.EPERM:
                # ignore chown failure as user could be editing file belonging
                # to a different user, in which case we really cant do anything
                # about it short of making the file update non-atomic
                raise

    temp.close()
    temp = temp.name
    try:
        container.commit(temp)
        atomic_rename(temp, path)
    finally:
        if os.path.exists(temp):
            os.remove(temp)
Пример #2
0
def get_cover(metadata):
    cdir = os.path.join(cache_dir(), 'icon-theme-covers')
    try:
        os.makedirs(cdir)
    except EnvironmentError as e:
        if e.errno != errno.EEXIST:
            raise

    def path(ext):
        return os.path.join(cdir, metadata['name'] + '.' + ext)

    etag_file, cover_file = map(path, 'etag jpg'.split())

    def safe_read(path):
        try:
            with open(path, 'rb') as f:
                return f.read()
        except EnvironmentError as e:
            if e.errno != errno.ENOENT:
                raise
        return b''

    etag, cached = safe_read(etag_file), safe_read(cover_file)
    etag = etag.decode('utf-8')
    cached, etag = download_cover(metadata['cover-url'], etag, cached)
    if cached:
        aname = cover_file + '.atomic'
        with open(aname, 'wb') as f:
            f.write(cached)
        atomic_rename(aname, cover_file)
    if etag:
        with open(etag_file, 'wb') as f:
            f.write(as_bytes(etag))
    return cached or b''
Пример #3
0
def save_container(container, path):
    temp = PersistentTemporaryFile(
        prefix=('_' if iswindows else '.'), suffix=os.path.splitext(path)[1], dir=os.path.dirname(path))
    if hasattr(os, 'fchmod'):
        # Ensure file permissions and owner information is preserved
        fno = temp.fileno()
        try:
            st = os.stat(path)
        except EnvironmentError as err:
            if err.errno != errno.ENOENT:
                raise
            # path may not exist if we are saving a copy, in which case we use
            # the metadata from the original book
            st = os.stat(container.path_to_ebook)
        os.fchmod(fno, st.st_mode)
        os.fchown(fno, st.st_uid, st.st_gid)

    temp.close()
    temp = temp.name
    try:
        container.commit(temp)
        atomic_rename(temp, path)
    finally:
        if os.path.exists(temp):
            os.remove(temp)
Пример #4
0
def atomic_write(name, raw):
    bdir, bname = os.path.dirname(
        os.path.abspath(name)), os.path.basename(name)
    tname = ('_' if iswindows else '.') + bname
    with open(os.path.join(bdir, tname), 'wb') as f:
        f.write(raw)
    atomic_rename(f.name, name)
Пример #5
0
def save_container(container, path):
    temp = PersistentTemporaryFile(
        prefix=('_' if iswindows else '.'), suffix=os.path.splitext(path)[1], dir=os.path.dirname(path))
    if hasattr(os, 'fchmod'):
        # Ensure file permissions and owner information is preserved
        fno = temp.fileno()
        try:
            st = os.stat(path)
        except EnvironmentError as err:
            if err.errno != errno.ENOENT:
                raise
            # path may not exist if we are saving a copy, in which case we use
            # the metadata from the original book
            st = os.stat(container.path_to_ebook)
        os.fchmod(fno, st.st_mode)
        try:
            os.fchown(fno, st.st_uid, st.st_gid)
        except EnvironmentError as err:
            if err.errno != errno.EPERM:
                # ignore chown failure as user could be editing file belonging
                # to a different user, in which case we really cant do anything
                # about it short of making the file update non-atomic
                raise

    temp.close()
    temp = temp.name
    try:
        container.commit(temp)
        atomic_rename(temp, path)
    finally:
        if os.path.exists(temp):
            os.remove(temp)
Пример #6
0
 def write_result(self, res):
     if self.write_result_to:
         with tempfile.NamedTemporaryFile(dir=os.path.dirname(self.write_result_to), delete=False) as f:
             src = f.name
             f.write(str(res).encode('utf-8'))
             f.flush()
         atomic_rename(src, self.write_result_to)
Пример #7
0
def run_optimizer(file_path, cmd, as_filter=False, input_data=None):
    file_path = os.path.abspath(file_path)
    cwd = os.path.dirname(file_path)
    fd, outfile = tempfile.mkstemp(dir=cwd)
    try:
        if as_filter:
            outf = os.fdopen(fd, 'wb')
        else:
            os.close(fd)
        iname, oname = os.path.basename(file_path), os.path.basename(outfile)
        def repl(q, r):
            cmd[cmd.index(q)] = r
        if not as_filter:
            repl(True, iname), repl(False, oname)
        if iswindows:
            # subprocess in python 2 cannot handle unicode strings that are not
            # encodeable in mbcs, so we fail here, where it is more explicit,
            # instead.
            cmd = [x.encode('mbcs') if isinstance(x, type('')) else x for x in cmd]
            if isinstance(cwd, type('')):
                cwd = cwd.encode('mbcs')
        stdin = subprocess.PIPE if as_filter else None
        stderr = subprocess.PIPE if as_filter else subprocess.STDOUT
        creationflags = 0x08 if iswindows else 0
        p = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE, stderr=stderr, stdin=stdin, creationflags=creationflags)
        stderr = p.stderr if as_filter else p.stdout
        if as_filter:
            src = input_data or open(file_path, 'rb')
            def copy(src, dest):
                try:
                    shutil.copyfileobj(src, dest)
                finally:
                    src.close(), dest.close()
            inw = Thread(name='CopyInput', target=copy, args=(src, p.stdin))
            inw.daemon = True
            inw.start()
            outw = Thread(name='CopyOutput', target=copy, args=(p.stdout, outf))
            outw.daemon = True
            outw.start()
        raw = force_unicode(stderr.read())
        if p.wait() != 0:
            return raw
        else:
            try:
                sz = os.path.getsize(outfile)
            except EnvironmentError:
                sz = 0
            if sz < 1:
                return raw
            shutil.copystat(file_path, outfile)
            atomic_rename(outfile, file_path)
    finally:
        try:
            os.remove(outfile)
        except EnvironmentError as err:
            if err.errno != errno.ENOENT:
                raise
Пример #8
0
def save_container(container, path):
    temp = PersistentTemporaryFile(
        prefix=('_' if iswindows else '.'), suffix=os.path.splitext(path)[1], dir=os.path.dirname(path))
    temp.close()
    temp = temp.name
    try:
        container.commit(temp)
        atomic_rename(temp, path)
    finally:
        if os.path.exists(temp):
            os.remove(temp)
Пример #9
0
def create_file_copy(ctx, rd, prefix, library_id, book_id, ext, mtime, copy_func, extra_etag_data=''):
    ''' We cannot copy files directly from the library folder to the output
    socket, as this can potentially lock the library for an extended period. So
    instead we copy out the data from the library folder into a temp folder. We
    make sure to only do this copy once, using the previous copy, if there have
    been no changes to the data for the file since the last copy. '''
    global rename_counter

    # Avoid too many items in a single directory for performance
    base = os.path.join(rd.tdir, 'fcache', (('%x' % book_id)[-3:]))
    if iswindows:
        base = '\\\\?\\' + os.path.abspath(base)  # Ensure fname is not too long for windows' API

    bname = '%s-%s-%x.%s' % (prefix, library_id, book_id, ext)
    if '\\' in bname or '/' in bname:
        raise ValueError('File components must not contain path separators')
    fname = os.path.join(base, bname)
    used_cache = 'no'

    with lock:
        previous_mtime = mtimes.get(bname)
        if previous_mtime is None or previous_mtime < mtime:
            if previous_mtime is not None:
                # File exists and may be open, so we cannot change its
                # contents, as that would lead to corrupted downloads in any
                # clients that are currently downloading the file.
                if iswindows:
                    # On windows in order to re-use bname, we have to rename it
                    # before deleting it
                    rename_counter += 1
                    dname = os.path.join(base, '_%x' % rename_counter)
                    atomic_rename(fname, dname)
                    os.remove(dname)
                else:
                    os.remove(fname)
            ans = open_for_write(fname)
            mtimes[bname] = mtime
            copy_func(ans)
            ans.seek(0)
        else:
            try:
                ans = share_open(fname, 'rb')
                used_cache = 'yes'
            except EnvironmentError as err:
                if err.errno != errno.ENOENT:
                    raise
                ans = open_for_write(fname)
                mtimes[bname] = mtime
                copy_func(ans)
                ans.seek(0)
        if ctx.testing:
            rd.outheaders['Used-Cache'] = used_cache
            rd.outheaders['Tempfile'] = hexlify(fname.encode('utf-8'))
        return rd.filesystem_file_with_custom_etag(ans, prefix, library_id, book_id, mtime, extra_etag_data)
Пример #10
0
def create_file_copy(ctx, rd, prefix, library_id, book_id, ext, mtime, copy_func, extra_etag_data=''):
    ''' We cannot copy files directly from the library folder to the output
    socket, as this can potentially lock the library for an extended period. So
    instead we copy out the data from the library folder into a temp folder. We
    make sure to only do this copy once, using the previous copy, if there have
    been no changes to the data for the file since the last copy. '''
    global rename_counter

    # Avoid too many items in a single directory for performance
    base = os.path.join(rd.tdir, 'fcache', (('%x' % book_id)[-3:]))
    if iswindows:
        base = '\\\\?\\' + os.path.abspath(base)  # Ensure fname is not too long for windows' API

    bname = '%s-%s-%x.%s' % (prefix, library_id, book_id, ext)
    if '\\' in bname or '/' in bname:
        raise ValueError('File components must not contain path separators')
    fname = os.path.join(base, bname)
    used_cache = 'no'

    with lock:
        previous_mtime = mtimes.get(bname)
        if previous_mtime is None or previous_mtime < mtime:
            if previous_mtime is not None:
                # File exists and may be open, so we cannot change its
                # contents, as that would lead to corrupted downloads in any
                # clients that are currently downloading the file.
                if iswindows:
                    # On windows in order to re-use bname, we have to rename it
                    # before deleting it
                    rename_counter += 1
                    dname = os.path.join(base, '_%x' % rename_counter)
                    atomic_rename(fname, dname)
                    os.remove(dname)
                else:
                    os.remove(fname)
            ans = open_for_write(fname)
            mtimes[bname] = mtime
            copy_func(ans)
            ans.seek(0)
        else:
            try:
                ans = share_open(fname, 'rb')
                used_cache = 'yes'
            except EnvironmentError as err:
                if err.errno != errno.ENOENT:
                    raise
                ans = open_for_write(fname)
                mtimes[bname] = mtime
                copy_func(ans)
                ans.seek(0)
        if ctx.testing:
            rd.outheaders['Used-Cache'] = used_cache
            rd.outheaders['Tempfile'] = hexlify(fname.encode('utf-8'))
        return rd.filesystem_file_with_custom_etag(ans, prefix, library_id, book_id, mtime, extra_etag_data)
Пример #11
0
def create_file_copy(ctx, rd, prefix, library_id, book_id, ext, mtime, copy_func, extra_etag_data=""):
    """ We cannot copy files directly from the library folder to the output
    socket, as this can potentially lock the library for an extended period. So
    instead we copy out the data from the library folder into a temp folder. We
    make sure to only do this copy once, using the previous copy, if there have
    been no changes to the data for the file since the last copy. """
    global rename_counter

    # Avoid too many items in a single directory for performance
    base = os.path.join(rd.tdir, "fcache", (("%x" % book_id)[-3:]))
    if iswindows:
        base = "\\\\?\\" + os.path.abspath(base)  # Ensure fname is not too long for windows' API

    bname = "%s-%s-%x.%s" % (prefix, library_id, book_id, ext)
    if "\\" in bname or "/" in bname:
        raise ValueError("File components must not contain path separators")
    fname = os.path.join(base, bname)
    used_cache = "no"

    with lock:
        previous_mtime = mtimes.get(bname)
        if previous_mtime is None or previous_mtime < mtime:
            if previous_mtime is not None:
                # File exists and may be open, so we cannot change its
                # contents, as that would lead to corrupted downloads in any
                # clients that are currently downloading the file.
                if iswindows:
                    # On windows in order to re-use bname, we have to rename it
                    # before deleting it
                    rename_counter += 1
                    dname = os.path.join(base, "_%x" % rename_counter)
                    atomic_rename(fname, dname)
                    os.remove(dname)
                else:
                    os.remove(fname)
            try:
                ans = share_open(fname, "w+b")
            except EnvironmentError:
                try:
                    os.makedirs(base)
                except EnvironmentError:
                    pass
                ans = share_open(fname, "w+b")
            mtimes[bname] = mtime
            copy_func(ans)
            ans.seek(0)
        else:
            ans = share_open(fname, "rb")
            used_cache = "yes"
        if ctx.testing:
            rd.outheaders["Used-Cache"] = used_cache
            rd.outheaders["Tempfile"] = hexlify(fname.encode("utf-8"))
        return rd.filesystem_file_with_custom_etag(ans, prefix, library_id, book_id, mtime, extra_etag_data)
Пример #12
0
 def rollover(self):
     if self.max_size is None or self.current_pos <= self.max_size:
         return
     self.stream.close()
     for i in xrange(self.history - 1, 0, -1):
         try:
             atomic_rename('%s.%d' % (self.filename, i), '%s.%d' % (self.filename, i+1))
         except EnvironmentError as e:
             if e.errno != errno.ENOENT:  # the source of the rename does not exist
                 raise
     atomic_rename(self.filename, '%s.%d' % (self.filename, 1))
     self.set_output()
Пример #13
0
def save_container(container, path):
    temp = PersistentTemporaryFile(prefix=('_' if iswindows else '.'),
                                   suffix=os.path.splitext(path)[1],
                                   dir=os.path.dirname(path))
    temp.close()
    temp = temp.name
    try:
        container.commit(temp)
        atomic_rename(temp, path)
    finally:
        if os.path.exists(temp):
            os.remove(temp)
Пример #14
0
def save_container(container, path):
    if container.is_dir:
        return save_dir_container(container, path)
    temp = PersistentTemporaryFile(prefix=('_' if iswindows else '.'),
                                   suffix=os.path.splitext(path)[1],
                                   dir=os.path.dirname(path))
    if hasattr(os, 'fchmod'):
        # Ensure file permissions and owner information is preserved
        fno = temp.fileno()
        st = None
        try:
            st = os.stat(path)
        except OSError as err:
            if err.errno != errno.ENOENT:
                raise
            # path may not exist if we are saving a copy, in which case we use
            # the metadata from the original book
            try:
                st = os.stat(container.path_to_ebook)
            except OSError as err:
                if err.errno != errno.ENOENT:
                    raise
                # Somebody deleted the original file
        if st is not None:
            try:
                os.fchmod(fno, st.st_mode)
            except OSError as err:
                if err.errno != errno.EPERM:
                    raise
                raise OSError(
                    'Failed to change permissions of {} to {} ({}), with error: {}. Most likely the {} directory has a restrictive umask'
                    .format(temp.name, oct(st.st_mode),
                            format_permissions(st.st_mode),
                            errno.errorcode[err.errno],
                            os.path.dirname(temp.name)))
            try:
                os.fchown(fno, st.st_uid, st.st_gid)
            except OSError as err:
                if err.errno not in (errno.EPERM, errno.EACCES):
                    # ignore chown failure as user could be editing file belonging
                    # to a different user, in which case we really can't do anything
                    # about it short of making the file update non-atomic
                    raise

    temp.close()
    temp = temp.name
    try:
        container.commit(temp)
        atomic_rename(temp, path)
    finally:
        if os.path.exists(temp):
            os.remove(temp)
Пример #15
0
 def rollover(self):
     if self.max_size is None or self.current_pos <= self.max_size:
         return
     self.stream.close()
     for i in xrange(self.history - 1, 0, -1):
         try:
             atomic_rename('%s.%d' % (self.filename, i),
                           '%s.%d' % (self.filename, i + 1))
         except EnvironmentError as e:
             if e.errno != errno.ENOENT:  # the source of the rename does not exist
                 raise
     atomic_rename(self.filename, '%s.%d' % (self.filename, 1))
     self.set_output()
Пример #16
0
def main(path_to_html, tdir, image_format='jpeg'):
    if image_format not in ('jpeg', 'png'):
        raise ValueError('Image format must be either jpeg or png')
    must_use_qt()
    path_to_html = os.path.abspath(path_to_html)
    os.chdir(tdir)
    renderer = Render()
    renderer.start_load(path_to_html)
    ret = QApplication.instance().exec_()
    if ret == 0:
        page_images('rendered.pdf', image_format=image_format)
        ext = {'jpeg': 'jpg'}.get(image_format, image_format)
        atomic_rename('page-images-1.' + ext, 'rendered.' + image_format)
    return ret == 0
Пример #17
0
 def do_save(self, tdir, container):
     temp = None
     try:
         path = container.path_to_ebook
         temp = PersistentTemporaryFile(
             prefix=('_' if iswindows else '.'), suffix=os.path.splitext(path)[1], dir=os.path.dirname(path))
         temp.close()
         temp = temp.name
         container.commit(temp)
         atomic_rename(temp, path)
     finally:
         if temp and os.path.exists(temp):
             os.remove(temp)
         shutil.rmtree(tdir, ignore_errors=True)
Пример #18
0
 def do_save(self, tdir, container):
     temp = None
     try:
         path = container.path_to_ebook
         temp = PersistentTemporaryFile(prefix=('_' if iswindows else '.'),
                                        suffix=os.path.splitext(path)[1],
                                        dir=os.path.dirname(path))
         temp.close()
         temp = temp.name
         container.commit(temp)
         atomic_rename(temp, path)
     finally:
         if temp and os.path.exists(temp):
             os.remove(temp)
         shutil.rmtree(tdir, ignore_errors=True)
Пример #19
0
def save_container(container, path):
    if container.is_dir:
        return save_dir_container(container, path)
    temp = PersistentTemporaryFile(
        prefix=('_' if iswindows else '.'), suffix=os.path.splitext(path)[1], dir=os.path.dirname(path))
    if hasattr(os, 'fchmod'):
        # Ensure file permissions and owner information is preserved
        fno = temp.fileno()
        st = None
        try:
            st = os.stat(path)
        except EnvironmentError as err:
            if err.errno != errno.ENOENT:
                raise
            # path may not exist if we are saving a copy, in which case we use
            # the metadata from the original book
            try:
                st = os.stat(container.path_to_ebook)
            except EnvironmentError as err:
                if err.errno != errno.ENOENT:
                    raise
                # Somebody deleted the original file
        if st is not None:
            try:
                os.fchmod(fno, st.st_mode)
            except EnvironmentError as err:
                if err.errno != errno.EPERM:
                    raise
                raise EnvironmentError('Failed to change permissions of %s to %s (%s), with error: %s. Most likely the %s directory has a restrictive umask' % (
                    temp.name, oct(st.st_mode), format_permissions(st.st_mode), errno.errorcode[err.errno], os.path.dirname(temp.name)))
            try:
                os.fchown(fno, st.st_uid, st.st_gid)
            except EnvironmentError as err:
                if err.errno not in (errno.EPERM, errno.EACCES):
                    # ignore chown failure as user could be editing file belonging
                    # to a different user, in which case we really cant do anything
                    # about it short of making the file update non-atomic
                    raise

    temp.close()
    temp = temp.name
    try:
        container.commit(temp)
        atomic_rename(temp, path)
    finally:
        if os.path.exists(temp):
            os.remove(temp)
Пример #20
0
def save_reading_rates(key, rates):
    existing = get_existing_reading_rates()
    existing.pop(key, None)
    existing[key] = rates
    while len(existing) > 50:
        expired = next(iter(existing))
        del existing[expired]
    ddata = json.dumps(existing, indent=2).encode('utf-8')
    path = reading_rates_path()
    try:
        with tempfile.NamedTemporaryFile(dir=os.path.dirname(path),
                                         delete=False) as f:
            f.write(ddata)
        atomic_rename(f.name, path)
    except Exception:
        import traceback
        traceback.print_exc()
Пример #21
0
def save_container(container, path):
    temp = PersistentTemporaryFile(
        prefix=('_' if iswindows else '.'), suffix=os.path.splitext(path)[1], dir=os.path.dirname(path))
    if hasattr(os, 'fchmod'):
        # Ensure file permissions and owner information is preserved
        fno = temp.fileno()
        st = os.stat(path)
        os.fchmod(fno, st.st_mode)
        os.fchown(fno, st.st_uid, st.st_gid)

    temp.close()
    temp = temp.name
    try:
        container.commit(temp)
        atomic_rename(temp, path)
    finally:
        if os.path.exists(temp):
            os.remove(temp)
Пример #22
0
def reinit_db(dbpath):
    from contextlib import closing
    from calibre import as_unicode
    from calibre.ptempfile import TemporaryFile
    from calibre.utils.filenames import atomic_rename
    # We have to use sqlite3 instead of apsw as apsw has no way to discard
    # problematic statements
    import sqlite3
    from calibre.library.sqlite import do_connect
    with TemporaryFile(suffix='_tmpdb.db',
                       dir=os.path.dirname(dbpath)) as tmpdb:
        with closing(do_connect(dbpath)) as src, closing(
                do_connect(tmpdb)) as dest:
            dest.execute(
                'create temporary table temp_sequence(id INTEGER PRIMARY KEY AUTOINCREMENT)'
            )
            dest.commit()
            uv = int(src.execute('PRAGMA user_version;').fetchone()[0])
            dump = src.iterdump()
            last_restore_error = None
            while True:
                try:
                    statement = next(dump)
                except StopIteration:
                    break
                except sqlite3.OperationalError as e:
                    prints('Failed to dump a line:', as_unicode(e))
                if last_restore_error:
                    prints('Failed to restore a line:', last_restore_error)
                    last_restore_error = None
                try:
                    dest.execute(statement)
                except sqlite3.OperationalError as e:
                    last_restore_error = as_unicode(e)
                    # The dump produces an extra commit at the end, so
                    # only print this error if there are more
                    # statements to be restored
            dest.execute('PRAGMA user_version=%d;' % uv)
            dest.commit()
        atomic_rename(tmpdb, dbpath)
    prints('Database successfully re-initialized')
Пример #23
0
def reinit_db(dbpath):
    from contextlib import closing
    from calibre import as_unicode
    from calibre.ptempfile import TemporaryFile
    from calibre.utils.filenames import atomic_rename

    # We have to use sqlite3 instead of apsw as apsw has no way to discard
    # problematic statements
    import sqlite3
    from calibre.library.sqlite import do_connect

    with TemporaryFile(suffix="_tmpdb.db", dir=os.path.dirname(dbpath)) as tmpdb:
        with closing(do_connect(dbpath)) as src, closing(do_connect(tmpdb)) as dest:
            dest.execute("create temporary table temp_sequence(id INTEGER PRIMARY KEY AUTOINCREMENT)")
            dest.commit()
            uv = int(src.execute("PRAGMA user_version;").fetchone()[0])
            dump = src.iterdump()
            last_restore_error = None
            while True:
                try:
                    statement = next(dump)
                except StopIteration:
                    break
                except sqlite3.OperationalError as e:
                    prints("Failed to dump a line:", as_unicode(e))
                if last_restore_error:
                    prints("Failed to restore a line:", last_restore_error)
                    last_restore_error = None
                try:
                    dest.execute(statement)
                except sqlite3.OperationalError as e:
                    last_restore_error = as_unicode(e)
                    # The dump produces an extra commit at the end, so
                    # only print this error if there are more
                    # statements to be restored
            dest.execute("PRAGMA user_version=%d;" % uv)
            dest.commit()
        atomic_rename(tmpdb, dbpath)
    prints("Database successfully re-initialized")
Пример #24
0
def safe_copy(src, destpath):
    tpath = destpath + '-temp'
    with open(tpath, 'wb') as dest:
        shutil.copyfileobj(src, dest)
    atomic_rename(tpath, destpath)
Пример #25
0
def run_optimizer(file_path, cmd, as_filter=False, input_data=None):
    file_path = os.path.abspath(file_path)
    cwd = os.path.dirname(file_path)
    ext = os.path.splitext(file_path)[1]
    if not ext or len(ext) > 10 or not ext.startswith("."):
        ext = ".jpg"
    fd, outfile = tempfile.mkstemp(dir=cwd, suffix=ext)
    try:
        if as_filter:
            outf = os.fdopen(fd, "wb")
        else:
            os.close(fd)
        iname, oname = os.path.basename(file_path), os.path.basename(outfile)

        def repl(q, r):
            cmd[cmd.index(q)] = r

        if not as_filter:
            repl(True, iname), repl(False, oname)
        if iswindows:
            # subprocess in python 2 cannot handle unicode strings that are not
            # encodeable in mbcs, so we fail here, where it is more explicit,
            # instead.
            cmd = [x.encode("mbcs") if isinstance(x, type("")) else x for x in cmd]
            if isinstance(cwd, type("")):
                cwd = cwd.encode("mbcs")
        stdin = subprocess.PIPE if as_filter else None
        stderr = subprocess.PIPE if as_filter else subprocess.STDOUT
        creationflags = 0x08 if iswindows else 0
        p = subprocess.Popen(
            cmd, cwd=cwd, stdout=subprocess.PIPE, stderr=stderr, stdin=stdin, creationflags=creationflags
        )
        stderr = p.stderr if as_filter else p.stdout
        if as_filter:
            src = input_data or open(file_path, "rb")

            def copy(src, dest):
                try:
                    shutil.copyfileobj(src, dest)
                finally:
                    src.close(), dest.close()

            inw = Thread(name="CopyInput", target=copy, args=(src, p.stdin))
            inw.daemon = True
            inw.start()
            outw = Thread(name="CopyOutput", target=copy, args=(p.stdout, outf))
            outw.daemon = True
            outw.start()
        raw = force_unicode(stderr.read())
        if p.wait() != 0:
            return raw
        else:
            if as_filter:
                outw.join(60.0), inw.join(60.0)
            try:
                sz = os.path.getsize(outfile)
            except EnvironmentError:
                sz = 0
            if sz < 1:
                return "%s returned a zero size image" % cmd[0]
            shutil.copystat(file_path, outfile)
            atomic_rename(outfile, file_path)
    finally:
        try:
            os.remove(outfile)
        except EnvironmentError as err:
            if err.errno != errno.ENOENT:
                raise
        try:
            os.remove(outfile + ".bak")  # optipng creates these files
        except EnvironmentError as err:
            if err.errno != errno.ENOENT:
                raise
Пример #26
0
 def atomic_write(name, content):
     name = os.path.join(base, name)
     tname = name + '.tmp'
     with lopen(tname, 'wb') as f:
         f.write(content)
     atomic_rename(tname, name)
Пример #27
0
def run_optimizer(file_path, cmd, as_filter=False, input_data=None):
    file_path = os.path.abspath(file_path)
    cwd = os.path.dirname(file_path)
    ext = os.path.splitext(file_path)[1]
    if not ext or len(ext) > 10 or not ext.startswith('.'):
        ext = '.jpg'
    fd, outfile = tempfile.mkstemp(dir=cwd, suffix=ext)
    try:
        if as_filter:
            outf = os.fdopen(fd, 'wb')
        else:
            os.close(fd)
        iname, oname = os.path.basename(file_path), os.path.basename(outfile)

        def repl(q, r):
            cmd[cmd.index(q)] = r

        if not as_filter:
            repl(True, iname), repl(False, oname)
        if iswindows:
            # subprocess in python 2 cannot handle unicode strings that are not
            # encodeable in mbcs, so we fail here, where it is more explicit,
            # instead.
            cmd = [
                x.encode('mbcs') if isinstance(x, type('')) else x for x in cmd
            ]
            if isinstance(cwd, type('')):
                cwd = cwd.encode('mbcs')
        stdin = subprocess.PIPE if as_filter else None
        stderr = subprocess.PIPE if as_filter else subprocess.STDOUT
        creationflags = 0x08 if iswindows else 0
        p = subprocess.Popen(cmd,
                             cwd=cwd,
                             stdout=subprocess.PIPE,
                             stderr=stderr,
                             stdin=stdin,
                             creationflags=creationflags)
        stderr = p.stderr if as_filter else p.stdout
        if as_filter:
            src = input_data or open(file_path, 'rb')

            def copy(src, dest):
                try:
                    shutil.copyfileobj(src, dest)
                finally:
                    src.close(), dest.close()

            inw = Thread(name='CopyInput', target=copy, args=(src, p.stdin))
            inw.daemon = True
            inw.start()
            outw = Thread(name='CopyOutput',
                          target=copy,
                          args=(p.stdout, outf))
            outw.daemon = True
            outw.start()
        raw = force_unicode(stderr.read())
        if p.wait() != 0:
            return raw
        else:
            if as_filter:
                outw.join(60.0), inw.join(60.0)
            try:
                sz = os.path.getsize(outfile)
            except EnvironmentError:
                sz = 0
            if sz < 1:
                return '%s returned a zero size image' % cmd[0]
            shutil.copystat(file_path, outfile)
            atomic_rename(outfile, file_path)
    finally:
        try:
            os.remove(outfile)
        except EnvironmentError as err:
            if err.errno != errno.ENOENT:
                raise
        try:
            os.remove(outfile + '.bak')  # optipng creates these files
        except EnvironmentError as err:
            if err.errno != errno.ENOENT:
                raise
Пример #28
0
def atomic_write(name, raw):
    bdir, bname = os.path.dirname(os.path.abspath(name)), os.path.basename(name)
    tname = ('_' if iswindows else '.') + bname
    with open(os.path.join(bdir, tname), 'wb') as f:
        f.write(raw)
    atomic_rename(f.name, name)
Пример #29
0
 def atomic_write(name, content):
     name = os.path.join(base, name)
     tname = name + '.tmp'
     with lopen(tname, 'wb') as f:
         f.write(content)
     atomic_rename(tname, name)
Пример #30
0
def safe_copy(src, destpath):
    tpath = destpath + '-temp'
    with open(tpath, 'wb') as dest:
        shutil.copyfileobj(src, dest)
    atomic_rename(tpath, destpath)