def commit(self, save_defaults=False): ''' Settings are stored in two attributes: `opf_file` and `cover_file`. Both may be None. Also returns a recommendation dictionary. ''' recs = self.commit_options(save_defaults) self.user_mi = mi = self.get_metadata() self.cover_file = self.opf_file = None if self.db is not None: if mi.title == self.db.title(self.book_id, index_is_id=True): mi.title_sort = self.db.title_sort(self.book_id, index_is_id=True) else: # Regenerate title sort taking into account book language languages = self.db.languages(self.book_id, index_is_id=True) if languages: lang = languages.split(',')[0] else: lang = None mi.title_sort = title_sort(mi.title, lang=lang) self.db.set_metadata(self.book_id, self.user_mi) self.mi, self.opf_file = create_opf_file(self.db, self.book_id) if self.cover_changed and self.cover_data is not None: self.db.set_cover(self.book_id, self.cover_data) cover = self.db.cover(self.book_id, index_is_id=True) if cover: cf = PersistentTemporaryFile('.jpeg') cf.write(cover) cf.close() self.cover_file = cf return recs
def view_device_book(self, path): pt = PersistentTemporaryFile('_view_device_book'+ os.path.splitext(path)[1]) self.persistent_files.append(pt) pt.close() self.gui.device_manager.view_book( Dispatcher(self.book_downloaded_for_viewing), path, pt.name)
def get_metadata(stream): from calibre.ebooks.metadata.archive import is_comic from calibre.ebooks.metadata.meta import get_metadata path = getattr(stream, 'name', False) if not path: pt = PersistentTemporaryFile('_rar-meta.rar') pt.write(stream.read()) pt.close() path = pt.name path = os.path.abspath(path) file_names = list(names(path)) if is_comic(file_names): return get_metadata(stream, 'cbr') for f in file_names: stream_type = os.path.splitext(f)[1].lower() if stream_type: stream_type = stream_type[1:] if stream_type in ('lit', 'opf', 'prc', 'mobi', 'fb2', 'epub', 'rb', 'imp', 'pdf', 'lrf', 'azw'): with TemporaryDirectory() as tdir: with CurrentDir(tdir): stream = extract_member(path, match=None, name=f, as_file=True)[1] return get_metadata(stream, stream_type) raise ValueError('No ebook found in RAR archive')
def fetch_scheduled_recipe(arg): # {{{ fmt = prefs['output_format'].lower() pt = PersistentTemporaryFile(suffix='_recipe_out.%s' % fmt.lower()) pt.close() recs = [] ps = load_defaults('page_setup') if 'output_profile' in ps: recs.append(('output_profile', ps['output_profile'], OptionRecommendation.HIGH)) lf = load_defaults('look_and_feel') if lf.get('base_font_size', 0.0) != 0.0: recs.append(('base_font_size', lf['base_font_size'], OptionRecommendation.HIGH)) recs.append( ('keep_ligatures', lf.get('keep_ligatures', False), OptionRecommendation.HIGH)) lr = load_defaults('lrf_output') if lr.get('header', False): recs.append(('header', True, OptionRecommendation.HIGH)) recs.append(('header_format', '%t', OptionRecommendation.HIGH)) epub = load_defaults('epub_output') if epub.get('epub_flatten', False): recs.append(('epub_flatten', True, OptionRecommendation.HIGH)) args = [arg['recipe'], pt.name, recs] if arg['username'] is not None: recs.append(('username', arg['username'], OptionRecommendation.HIGH)) if arg['password'] is not None: recs.append(('password', arg['password'], OptionRecommendation.HIGH)) return 'gui_convert', args, _( 'Fetch news from ') + arg['title'], fmt.upper(), [pt]
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)
def rebuild_it(self): from calibre.ebooks.tweak import get_tools, WorkerError src_dir = self._exploded det_msg = None of = PersistentTemporaryFile('_tweak_rebuild.'+self.current_format.lower()) of.close() of = of.name self._cleanup_files.append(of) try: rebuilder = get_tools(self.current_format)[1] rebuilder(src_dir, of) except WorkerError as e: det_msg = e.orig_tb except: import traceback det_msg = traceback.format_exc() finally: self.hide_msg() if det_msg is not None: error_dialog(self, _('Failed to rebuild file'), _('Failed to rebuild %s. For more information, click ' '"Show details".')%self.current_format, det_msg=det_msg, show=True) return None return of
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)
def __init__(self, url, fname, parent): QDialog.__init__(self, parent) self.setWindowTitle(_('Download %s')%fname) self.l = QVBoxLayout(self) self.purl = urlparse(url) self.msg = QLabel(_('Downloading <b>%(fname)s</b> from %(url)s')%dict( fname=fname, url=self.purl.netloc)) self.msg.setWordWrap(True) self.l.addWidget(self.msg) self.pb = QProgressBar(self) self.pb.setMinimum(0) self.pb.setMaximum(0) self.l.addWidget(self.pb) self.bb = QDialogButtonBox(QDialogButtonBox.Cancel, Qt.Horizontal, self) self.l.addWidget(self.bb) self.bb.rejected.connect(self.reject) sz = self.sizeHint() self.resize(max(sz.width(), 400), sz.height()) fpath = PersistentTemporaryFile(os.path.splitext(fname)[1]) fpath.close() self.fpath = fpath.name self.worker = Worker(url, self.fpath, Queue()) self.rejected = False
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)
def _write_new_cover(new_cdata, cpath): from calibre.utils.magick.draw import save_cover_data_to new_cover = PersistentTemporaryFile(suffix=os.path.splitext(cpath)[1]) new_cover.close() save_cover_data_to(new_cdata, new_cover.name) return new_cover
def do_download(self, urn): self.lock.lock() try: account_info = self.recipe_model.get_account_info(urn) customize_info = self.recipe_model.get_customize_info(urn) recipe = self.recipe_model.recipe_from_urn(urn) un = pw = None if account_info is not None: un, pw = account_info add_title_tag, custom_tags, keep_issues = customize_info script = self.recipe_model.get_recipe(urn) pt = PersistentTemporaryFile('_builtin.recipe') pt.write(script) pt.close() arg = { 'username': un, 'password': pw, 'add_title_tag':add_title_tag, 'custom_tags':custom_tags, 'recipe':pt.name, 'title':recipe.get('title',''), 'urn':urn, 'keep_issues':keep_issues } self.download_queue.add(urn) self.start_recipe_fetch.emit(arg) finally: self.lock.unlock()
def get_metadata(stream, cpath=None): if not podofo: raise Unavailable(podofo_err) pt = PersistentTemporaryFile('_podofo.pdf') pt.write(stream.read()) pt.close() server = Server(pool_size=1) job = ParallelJob('read_pdf_metadata', 'Read pdf metadata', lambda x,y:x, args=[pt.name, cpath]) server.add_job(job) while not job.is_finished: time.sleep(0.1) job.update() job.update() server.close() if job.result is None: raise ValueError('Failed to read metadata: ' + job.details) title, authors, creator, tags, ok = job.result if not ok: print 'Failed to extract cover:' print job.details if title == '_': title = getattr(stream, 'name', _('Unknown')) title = os.path.splitext(title)[0] mi = MetaInformation(title, authors) if creator: mi.book_producer = creator if tags: mi.tags = tags if os.path.exists(pt.name): os.remove(pt.name) if ok: mi.cover = cpath return mi
def convert(self, stream, options, file_ext, log, accelerators): from calibre.ebooks.txt.processor import convert_basic stdout = StringIO() ppdjvu = True # using djvutxt is MUCH faster, should make it an option if options.use_djvutxt and os.path.exists('/usr/bin/djvutxt'): from calibre.ptempfile import PersistentTemporaryFile try: fp = PersistentTemporaryFile(suffix='.djvu', prefix='djv_input') filename = fp._name fp.write(stream.read()) fp.close() cmd = ['djvutxt', filename] stdout.write( Popen(cmd, stdout=PIPE, close_fds=True).communicate()[0]) os.remove(filename) ppdjvu = False except: stream.seek(0) # retry with the pure python converter if ppdjvu: from calibre.ebooks.djvu.djvu import DJVUFile x = DJVUFile(stream) x.get_text(stdout) html = convert_basic(stdout.getvalue().replace(b"\n", b' ').replace( b'\037', b'\n\n')) # Run the HTMLized text through the html processing plugin. from calibre.customize.ui import plugin_for_input_format html_input = plugin_for_input_format('html') for opt in html_input.options: setattr(options, opt.option.name, opt.recommended_value) options.input_encoding = 'utf-8' base = os.getcwdu() if file_ext != 'txtz' and hasattr(stream, 'name'): base = os.path.dirname(stream.name) fname = os.path.join(base, 'index.html') c = 0 while os.path.exists(fname): c += 1 fname = 'index%d.html' % c htmlfile = open(fname, 'wb') with htmlfile: htmlfile.write(html.encode('utf-8')) odi = options.debug_pipeline options.debug_pipeline = None # Generate oeb from html conversion. with open(htmlfile.name, 'rb') as f: oeb = html_input.convert(f, options, 'html', log, {}) options.debug_pipeline = odi os.remove(htmlfile.name) # Set metadata from file. from calibre.customize.ui import get_file_type_metadata from calibre.ebooks.oeb.transforms.metadata import meta_info_to_oeb_metadata mi = get_file_type_metadata(stream, file_ext) meta_info_to_oeb_metadata(mi, oeb.metadata, log) return oeb
def fetch_scheduled_recipe(arg): # {{{ fmt = prefs['output_format'].lower() pt = PersistentTemporaryFile(suffix='_recipe_out.%s'%fmt.lower()) pt.close() recs = [] ps = load_defaults('page_setup') if 'output_profile' in ps: recs.append(('output_profile', ps['output_profile'], OptionRecommendation.HIGH)) lf = load_defaults('look_and_feel') if lf.get('base_font_size', 0.0) != 0.0: recs.append(('base_font_size', lf['base_font_size'], OptionRecommendation.HIGH)) recs.append(('keep_ligatures', lf.get('keep_ligatures', False), OptionRecommendation.HIGH)) lr = load_defaults('lrf_output') if lr.get('header', False): recs.append(('header', True, OptionRecommendation.HIGH)) recs.append(('header_format', '%t', OptionRecommendation.HIGH)) epub = load_defaults('epub_output') if epub.get('epub_flatten', False): recs.append(('epub_flatten', True, OptionRecommendation.HIGH)) args = [arg['recipe'], pt.name, recs] if arg['username'] is not None: recs.append(('username', arg['username'], OptionRecommendation.HIGH)) if arg['password'] is not None: recs.append(('password', arg['password'], OptionRecommendation.HIGH)) return 'gui_convert', args, _('Fetch news from ')+arg['title'], fmt.upper(), [pt]
def get_cookies(self): ''' Writes QNetworkCookies to Mozilla cookie .txt file. :return: The file path to the cookie file. ''' cf = PersistentTemporaryFile(suffix='.txt') cf.write('# Netscape HTTP Cookie File\n\n') for c in self.page().networkAccessManager().cookieJar().allCookies(): cookie = [] domain = unicode(c.domain()) cookie.append(domain) cookie.append('TRUE' if domain.startswith('.') else 'FALSE') cookie.append(unicode(c.path())) cookie.append('TRUE' if c.isSecure() else 'FALSE') cookie.append(unicode(c.expirationDate().toTime_t())) cookie.append(unicode(c.name())) cookie.append(unicode(c.value())) cf.write('\t'.join(cookie)) cf.write('\n') cf.close() return cf.name
def view_device_book(self, path): pt = PersistentTemporaryFile('_view_device_book' + os.path.splitext(path)[1]) self.persistent_files.append(pt) pt.close() self.gui.device_manager.view_book( Dispatcher(self.book_downloaded_for_viewing), path, pt.name)
def paste_image(self): c = QApplication.instance().clipboard() img = c.image() if img.isNull(): img = c.image(QClipboard.Mode.Selection) if img.isNull(): return error_dialog(self, _('No image'), _('There is no image on the clipboard'), show=True) d = ChooseName('image.jpg', self) if d.exec_() == QDialog.DialogCode.Accepted and d.filename: fmt = d.filename.rpartition('.')[-1].lower() if fmt not in {'jpg', 'jpeg', 'png'}: return error_dialog( self, _('Invalid file extension'), _('The file name you choose must have a .jpg or .png extension' ), show=True) t = PersistentTemporaryFile(prefix='editor-paste-image-', suffix='.' + fmt) t.write(pixmap_to_data(img, fmt)) t.close() self.chosen_image_is_external = (d.filename, t.name) self.accept()
def add_empty(self, *args): ''' Add an empty book item to the library. This does not import any formats from a book file. ''' author = series = title = None index = self.gui.library_view.currentIndex() if index.isValid(): raw = index.model().db.authors(index.row()) if raw: authors = [a.strip().replace('|', ',') for a in raw.split(',')] if authors: author = authors[0] series = index.model().db.series(index.row()) title = index.model().db.title(index.row()) dlg = AddEmptyBookDialog(self.gui, self.gui.library_view.model().db, author, series, dup_title=title) if dlg.exec_() == dlg.Accepted: temp_files = [] num = dlg.qty_to_add series = dlg.selected_series title = dlg.selected_title or _('Unknown') db = self.gui.library_view.model().db ids, orig_fmts = [], [] if dlg.duplicate_current_book: origmi = db.get_metadata(index.row(), get_cover=True, cover_as_data=True) if dlg.copy_formats.isChecked(): book_id = db.id(index.row()) orig_fmts = tuple(db.new_api.format(book_id, fmt, as_path=True) for fmt in db.new_api.formats(book_id)) for x in xrange(num): if dlg.duplicate_current_book: mi = origmi else: mi = MetaInformation(title, dlg.selected_authors) if series: mi.series = series mi.series_index = db.get_next_series_num_for(series) fmts = [] empty_format = gprefs.get('create_empty_format_file', '') if dlg.duplicate_current_book and dlg.copy_formats.isChecked(): fmts = orig_fmts elif empty_format: from calibre.ebooks.oeb.polish.create import create_book pt = PersistentTemporaryFile(suffix='.' + empty_format) pt.close() temp_files.append(pt.name) create_book(mi, pt.name, fmt=empty_format) fmts = [pt.name] ids.append(db.import_book(mi, fmts)) tuple(map(os.remove, orig_fmts)) self.gui.library_view.model().books_added(num) self.gui.refresh_cover_browser() self.gui.tags_view.recount() if ids: ids.reverse() self.gui.library_view.select_rows(ids) for path in temp_files: os.remove(path)
def convert(self, stream, options, file_ext, log, accelerators): from calibre.ebooks.txt.processor import convert_basic stdout = StringIO() ppdjvu = True # using djvutxt is MUCH faster, should make it an option if options.use_djvutxt and os.path.exists('/usr/bin/djvutxt'): from calibre.ptempfile import PersistentTemporaryFile try: fp = PersistentTemporaryFile(suffix='.djvu', prefix='djv_input') filename = fp._name fp.write(stream.read()) fp.close() cmd = ['djvutxt', filename] stdout.write(Popen(cmd, stdout=PIPE, close_fds=True).communicate()[0]) os.remove(filename) ppdjvu = False except: stream.seek(0) # retry with the pure python converter if ppdjvu: from calibre.ebooks.djvu.djvu import DJVUFile x = DJVUFile(stream) x.get_text(stdout) html = convert_basic(stdout.getvalue().replace(b"\n", b' ').replace( b'\037', b'\n\n')) # Run the HTMLized text through the html processing plugin. from calibre.customize.ui import plugin_for_input_format html_input = plugin_for_input_format('html') for opt in html_input.options: setattr(options, opt.option.name, opt.recommended_value) options.input_encoding = 'utf-8' base = os.getcwdu() if file_ext != 'txtz' and hasattr(stream, 'name'): base = os.path.dirname(stream.name) fname = os.path.join(base, 'index.html') c = 0 while os.path.exists(fname): c += 1 fname = 'index%d.html'%c htmlfile = open(fname, 'wb') with htmlfile: htmlfile.write(html.encode('utf-8')) odi = options.debug_pipeline options.debug_pipeline = None # Generate oeb from html conversion. with open(htmlfile.name, 'rb') as f: oeb = html_input.convert(f, options, 'html', log, {}) options.debug_pipeline = odi os.remove(htmlfile.name) # Set metadata from file. from calibre.customize.ui import get_file_type_metadata from calibre.ebooks.oeb.transforms.metadata import meta_info_to_oeb_metadata mi = get_file_type_metadata(stream, file_ext) meta_info_to_oeb_metadata(mi, oeb.metadata, log) return oeb
def create_cover_file(db, book_id): cover = db.cover(book_id, index_is_id=True) cf = None if cover: cf = PersistentTemporaryFile('.jpeg') cf.write(cover) cf.close() return cf
def generate_catalog(parent, dbspec, ids, device_manager, db): # {{{ from calibre.gui2.dialogs.catalog import Catalog # Build the Catalog dialog in gui2.dialogs.catalog d = Catalog(parent, dbspec, ids, db) if d.exec_() != d.Accepted: return None # Create the output file out = PersistentTemporaryFile(suffix='_catalog_out.'+d.catalog_format.lower()) # Profile the connected device # Parallel initialization in calibre.library.cli:command_catalog() connected_device = { 'is_device_connected': device_manager.is_device_connected, 'kind': device_manager.connected_device_kind, 'name': None, 'save_template': None, 'serial': None, 'storage': None } if device_manager.is_device_connected: device = device_manager.device connected_device['name'] = device.get_gui_name() try: storage = [] if device._main_prefix: storage.append(os.path.join(device._main_prefix, device.EBOOK_DIR_MAIN)) if device._card_a_prefix: storage.append(os.path.join(device._card_a_prefix, device.EBOOK_DIR_CARD_A)) if device._card_b_prefix: storage.append(os.path.join(device._card_b_prefix, device.EBOOK_DIR_CARD_B)) connected_device['storage'] = storage connected_device['serial'] = device.detected_device.serial if \ hasattr(device.detected_device,'serial') else None connected_device['save_template'] = device.save_template() except: pass # These args are passed inline to gui2.convert.gui_conversion:gui_catalog args = [ d.catalog_format, d.catalog_title, dbspec, ids, out.name, d.catalog_sync, d.fmt_options, connected_device ] out.close() # This returns to gui2.actions.catalog:generate_catalog() # Which then calls gui2.convert.gui_conversion:gui_catalog() with the args inline return 'gui_catalog', args, _('Generate catalog'), out.name, d.catalog_sync, \ d.catalog_title
def add_empty_format(self, format_): if self.gui.stack.currentIndex() != 0: return view = self.gui.library_view rows = view.selectionModel().selectedRows() if not rows: return error_dialog(self.gui, _('No books selected'), _('Cannot add files as no books are selected'), show=True) ids = [view.model().id(r) for r in rows] if len(ids) > 1 and not question_dialog( self.gui, _('Are you sure?'), _('Are you sure you want to add the same' ' empty file to all %d books? If the format' ' already exists for a book, it will be replaced.') % len(ids)): return db = self.gui.library_view.model().db if len(ids) == 1: formats = db.formats(ids[0], index_is_id=True) if formats: formats = {x.lower() for x in formats.split(',')} if format_ in formats: title = db.title(ids[0], index_is_id=True) msg = _( 'The {0} format will be replaced in the book {1}. Are you sure?' ).format(format_, title) if not confirm(msg, 'confirm_format_override_on_add', title=_('Are you sure?'), parent=self.gui): return for id_ in ids: from calibre.ebooks.oeb.polish.create import create_book pt = PersistentTemporaryFile(suffix='.' + format_) pt.close() try: mi = db.new_api.get_metadata(id_, get_cover=False, get_user_categories=False, cover_as_data=False) create_book(mi, pt.name, fmt=format_) db.add_format_with_hooks(id_, format_, pt.name, index_is_id=True, notify=True) finally: os.remove(pt.name) current_idx = self.gui.library_view.currentIndex() if current_idx.isValid(): view.model().current_changed(current_idx, current_idx)
def generate_catalog(parent, dbspec, ids, device_manager, db): # {{{ from calibre.gui2.dialogs.catalog import Catalog # Build the Catalog dialog in gui2.dialogs.catalog d = Catalog(parent, dbspec, ids, db) if d.exec_() != d.Accepted: return None # Create the output file out = PersistentTemporaryFile(suffix='_catalog_out.' + d.catalog_format.lower()) # Profile the connected device # Parallel initialization in calibre.db.cli.cmd_catalog connected_device = { 'is_device_connected': device_manager.is_device_present, 'kind': device_manager.connected_device_kind, 'name': None, 'save_template': None, 'serial': None, 'storage': None } if device_manager.is_device_present: device = device_manager.device connected_device['name'] = device.get_gui_name() try: storage = [] if device._main_prefix: storage.append( os.path.join(device._main_prefix, device.EBOOK_DIR_MAIN)) if device._card_a_prefix: storage.append( os.path.join(device._card_a_prefix, device.EBOOK_DIR_CARD_A)) if device._card_b_prefix: storage.append( os.path.join(device._card_b_prefix, device.EBOOK_DIR_CARD_B)) connected_device['storage'] = storage connected_device['serial'] = device.detected_device.serial if \ hasattr(device.detected_device,'serial') else None connected_device['save_template'] = device.save_template() except: pass # These args are passed inline to gui2.convert.gui_conversion:gui_catalog args = [ d.catalog_format, d.catalog_title, dbspec, ids, out.name, d.catalog_sync, d.fmt_options, connected_device ] out.close() # This returns to gui2.actions.catalog:generate_catalog() # Which then calls gui2.convert.gui_conversion:gui_catalog() with the args inline return 'gui_catalog', args, _('Generate catalog'), out.name, d.catalog_sync, \ d.catalog_title
def render_inline_toc(self): self.rendered_inline_toc = True from calibre.ebooks.pdf.render.toc import toc_as_html raw = toc_as_html(self.toc, self.doc, self.opts) pt = PersistentTemporaryFile('_pdf_itoc.htm') pt.write(raw) pt.close() self.render_queue.append(pt.name) self.render_next()
def _download_zip(self, plugin_zip_url): from calibre.ptempfile import PersistentTemporaryFile br = browser() br.set_handle_gzip(True) raw = br.open_novisit(plugin_zip_url).read() pt = PersistentTemporaryFile('.zip') pt.write(raw) pt.close() return pt.name
def dump(self, items, out_stream, pdf_metadata): f = PersistentTemporaryFile('_comic2pdf.pdf') f.close() try: self.render_images(f.name, pdf_metadata, items) with open(f.name, 'rb') as x: shutil.copyfileobj(x, out_stream) finally: os.remove(f.name)
def prince_convert(self): ''' Call the actual Prince command to convert to PDF ''' from os import makedirs from os.path import dirname, join, exists from calibre.ptempfile import PersistentTemporaryFile from calibre.constants import DEBUG # All files are relative to the OPF location opf_dir = dirname(self.opf) base_dir = dirname(self.pdf_file) base_dir = join(opf_dir, base_dir) try: makedirs(base_dir) except BaseException: if not exists(base_dir): raise # Create a temporary CSS file with the box contents custom_CSS = PersistentTemporaryFile() custom_CSS.write(unicode(self.css1.toPlainText())) custom_CSS.close() # Create a temporary file with the list of input files file_list = PersistentTemporaryFile() for item in self.oeb.spine: file_list.write(item.href + "\n") file_list.close() # Build the command line command = prefs['prince_exe'] args = ['-v'] if self.prince_file: args.append('-s') args.append(self.prince_file) args.append('-s') args.append(custom_CSS.name) args.append('-l') args.append(file_list.name) args.append('-o') args.append(self.pdf_file) # Hide the convert button and show a busy indicator self.convert.setEnabled(False) self.progress_bar = QProgressBar() self.progress_bar.setRange(0,0) self.progress_bar.setValue(0) self.l.addWidget(self.progress_bar) # Run the command and return the path to the PDF file if DEBUG: print(_('Converting book...')) process = QProcess(self) process.setWorkingDirectory(opf_dir) process.setProcessChannelMode(QProcess.MergedChannels); process.error.connect(self.error) process.finished.connect(self.end) self.process = process process.start(command, args)
def render_inline_toc(self): evaljs = self.view.page().mainFrame().evaluateJavaScript self.rendered_inline_toc = True from calibre.ebooks.pdf.render.toc import toc_as_html raw = toc_as_html(self.toc, self.doc, self.opts, evaljs) pt = PersistentTemporaryFile('_pdf_itoc.htm') pt.write(raw) pt.close() self.render_queue.append(pt.name) self.render_next()
def test_roundtrip(): ebook = get_container(sys.argv[-1]) p = PersistentTemporaryFile(suffix='.'+sys.argv[-1].rpartition('.')[-1]) p.close() ebook.commit(outpath=p.name) ebook2 = get_container(p.name) ebook3 = get_container(p.name) diff = ebook3.compare_to(ebook2) if diff is not None: print (diff)
def test_roundtrip(): ebook = get_container(sys.argv[-1]) p = PersistentTemporaryFile(suffix='.' + sys.argv[-1].rpartition('.')[-1]) p.close() ebook.commit(outpath=p.name) ebook2 = get_container(p.name) ebook3 = get_container(p.name) diff = ebook3.compare_to(ebook2) if diff is not None: print(diff)
def create_opf_file(db, book_id): mi = db.get_metadata(book_id, index_is_id=True) mi.application_id = uuid.uuid4() old_cover = mi.cover mi.cover = None raw = metadata_to_opf(mi) mi.cover = old_cover opf_file = PersistentTemporaryFile('.opf') opf_file.write(raw) opf_file.close() return mi, opf_file
def run_import_plugins(path_or_stream, fmt): fmt = fmt.lower() if hasattr(path_or_stream, 'seek'): path_or_stream.seek(0) pt = PersistentTemporaryFile('_import_plugin.'+fmt) shutil.copyfileobj(path_or_stream, pt, 1024**2) pt.close() path = pt.name else: path = path_or_stream return run_plugins_on_import(path, fmt)
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)
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)
def add_empty_format_to_book(self, book_id, fmt): from calibre.ebooks.oeb.polish.create import create_book db = self.gui.current_db pt = PersistentTemporaryFile(suffix='.' + fmt.lower()) pt.close() try: mi = db.new_api.get_metadata(book_id, get_cover=False, get_user_categories=False, cover_as_data=False) create_book(mi, pt.name, fmt=fmt.lower()) db.add_format_with_hooks(book_id, fmt, pt.name, index_is_id=True, notify=True) finally: os.remove(pt.name)
def fetch_scheduled_recipe(arg): # {{{ fmt = prefs['output_format'].lower() # Never use AZW3 for periodicals... if fmt == 'azw3': fmt = 'mobi' pt = PersistentTemporaryFile(suffix='_recipe_out.%s' % fmt.lower()) pt.close() recs = [] ps = load_defaults('page_setup') if 'output_profile' in ps: recs.append(('output_profile', ps['output_profile'], OptionRecommendation.HIGH)) for edge in ('left', 'top', 'bottom', 'right'): edge = 'margin_' + edge if edge in ps: recs.append((edge, ps[edge], OptionRecommendation.HIGH)) lf = load_defaults('look_and_feel') if lf.get('base_font_size', 0.0) != 0.0: recs.append(('base_font_size', lf['base_font_size'], OptionRecommendation.HIGH)) recs.append( ('keep_ligatures', lf.get('keep_ligatures', False), OptionRecommendation.HIGH)) lr = load_defaults('lrf_output') if lr.get('header', False): recs.append(('header', True, OptionRecommendation.HIGH)) recs.append(('header_format', '%t', OptionRecommendation.HIGH)) epub = load_defaults('epub_output') if epub.get('epub_flatten', False): recs.append(('epub_flatten', True, OptionRecommendation.HIGH)) if fmt == 'pdf': pdf = load_defaults('pdf_output') from calibre.customize.ui import plugin_for_output_format p = plugin_for_output_format('pdf') for opt in p.options: recs.append( (opt.option.name, pdf.get(opt.option.name, opt.recommended_value), OptionRecommendation.HIGH)) args = [arg['recipe'], pt.name, recs] if arg['username'] is not None: recs.append(('username', arg['username'], OptionRecommendation.HIGH)) if arg['password'] is not None: recs.append(('password', arg['password'], OptionRecommendation.HIGH)) return 'gui_convert', args, _( 'Fetch news from %s') % arg['title'], fmt.upper(), [pt]
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)
def calibre_cover(title, author_string, series_string=None, output_format='jpg', title_size=46, author_size=36, logo_path=None): title = normalize(title) author_string = normalize(author_string) series_string = normalize(series_string) from calibre.utils.magick.draw import create_cover_page, TextLine import regex pat = regex.compile( ur'\p{Cf}+', flags=regex.VERSION1) # remove non-printing chars like the soft hyphen text = pat.sub(u'', title + author_string + (series_string or u'')) font_path = P('fonts/liberation/LiberationSerif-Bold.ttf') from calibre.utils.fonts.utils import get_font_for_text font = open(font_path, 'rb').read() c = get_font_for_text(text, font) cleanup = False if c is not None and c != font: from calibre.ptempfile import PersistentTemporaryFile pt = PersistentTemporaryFile('.ttf') pt.write(c) pt.close() font_path = pt.name cleanup = True lines = [ TextLine(pat.sub(u'', title), title_size, font_path=font_path), TextLine(pat.sub(u'', author_string), author_size, font_path=font_path) ] if series_string: lines.append( TextLine(pat.sub(u'', series_string), author_size, font_path=font_path)) if logo_path is None: logo_path = I('library.png') try: return create_cover_page(lines, logo_path, output_format='jpg', texture_opacity=0.3, texture_data=I('cover_texture.png', data=True)) finally: if cleanup: os.remove(font_path)
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)
def download_cover(self, url): from calibre import browser from PIL import Image from cStringIO import StringIO from calibre.ptempfile import PersistentTemporaryFile self.log('Downloading cover from %r'%url) br = browser() raw = br.open_novisit(url).read() buf = StringIO(raw) pt = PersistentTemporaryFile('.jpg') pt.close() img = Image.open(buf) img.convert('RGB').save(pt.name) return pt.name
def add_empty(self, *args): ''' Add an empty book item to the library. This does not import any formats from a book file. ''' author = series = None index = self.gui.library_view.currentIndex() if index.isValid(): raw = index.model().db.authors(index.row()) if raw: authors = [a.strip().replace('|', ',') for a in raw.split(',')] if authors: author = authors[0] series = index.model().db.series(index.row()) dlg = AddEmptyBookDialog(self.gui, self.gui.library_view.model().db, author, series) if dlg.exec_() == dlg.Accepted: temp_files = [] num = dlg.qty_to_add series = dlg.selected_series title = dlg.selected_title or _('Unknown') db = self.gui.library_view.model().db ids = [] for x in xrange(num): mi = MetaInformation(title, dlg.selected_authors) if series: mi.series = series mi.series_index = db.get_next_series_num_for(series) fmts = [] empty_format = gprefs.get('create_empty_format_file', '') if empty_format: from calibre.ebooks.oeb.polish.create import create_book pt = PersistentTemporaryFile(suffix='.' + empty_format) pt.close() temp_files.append(pt.name) create_book(mi, pt.name, fmt=empty_format) fmts = [pt.name] ids.append(db.import_book(mi, fmts)) self.gui.library_view.model().books_added(num) if hasattr(self.gui, 'db_images'): self.gui.db_images.beginResetModel( ), self.gui.db_images.endResetModel() self.gui.tags_view.recount() if ids: ids.reverse() self.gui.library_view.select_rows(ids) for path in temp_files: os.remove(path)
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)
def __init__(self, text, font_size, bottom_margin=30, font_path=None): self.text, self.font_size, = text, font_size self.bottom_margin = bottom_margin if font_path is None: if not isinstance(text, unicode): text = force_unicode(text) from calibre.utils.fonts.utils import get_font_for_text fd = get_font_for_text(text) if fd is not None: from calibre.ptempfile import PersistentTemporaryFile pt = PersistentTemporaryFile('.ttf') pt.write(fd) pt.close() font_path = pt.name self.font_path = font_path
def start_download(gui, ids, callback, ensure_fields=None): d = ConfirmDialog(ids, gui) ret = d.exec_() d.b.clicked.disconnect() if ret != d.Accepted: return tf = PersistentTemporaryFile('_metadata_bulk.log') tf.close() job = Job('metadata bulk download', _('Download metadata for %d books')%len(ids), download, (ids, tf.name, gui.current_db, d.identify, d.covers, ensure_fields), {}, callback) job.download_debug_log = tf.name gui.job_manager.run_threaded_job(job) gui.status_bar.show_message(_('Metadata download started'), 3000)
def build_plugin(path): from calibre import prints from calibre.ptempfile import PersistentTemporaryFile from calibre.utils.zipfile import ZipFile, ZIP_STORED path = type(u'')(path) names = frozenset(os.listdir(path)) if u'__init__.py' not in names: prints(path, ' is not a valid plugin') raise SystemExit(1) t = PersistentTemporaryFile(u'.zip') with ZipFile(t, u'w', ZIP_STORED) as zf: zf.add_dir(path, simple_filter=lambda x:x in {'.git', '.bzr', '.svn', '.hg'}) t.close() plugin = add_plugin(t.name) os.remove(t.name) prints(u'Plugin updated:', plugin.name, plugin.version)
def build_plugin(path): from calibre import prints from calibre.ptempfile import PersistentTemporaryFile from calibre.utils.zipfile import ZipFile, ZIP_STORED path = type(u'')(path) names = frozenset(os.listdir(path)) if u'__init__.py' not in names: prints(path, ' is not a valid plugin') raise SystemExit(1) t = PersistentTemporaryFile(u'.zip') with ZipFile(t, u'w', ZIP_STORED) as zf: zf.add_dir(path) t.close() plugin = add_plugin(t.name) os.remove(t.name) prints(u'Plugin updated:', plugin.name, plugin.version)