示例#1
0
 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
示例#2
0
文件: rar.py 项目: Eksmo/calibre
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')
示例#3
0
文件: __init__.py 项目: Eksmo/calibre
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
示例#4
0
    def _download(self, cookie_file, url, filename, save_loc, add_to_lib):
        dfilename = ''

        if not url:
            raise Exception(_('No file specified to download.'))
        if not save_loc and not add_to_lib:
            # Nothing to do.
            return dfilename

        if not filename:
            filename = get_download_filename(url, cookie_file)
            filename, ext = os.path.splitext(filename)
            filename = filename[:60] + ext
            filename = ascii_filename(filename)

        br = browser()
        if cookie_file:
            cj = MozillaCookieJar()
            cj.load(cookie_file)
            br.set_cookiejar(cj)
        with closing(br.open(url)) as r:
            tf = PersistentTemporaryFile(suffix=filename)
            tf.write(r.read())
            dfilename = tf.name

        return dfilename
示例#5
0
 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()
示例#6
0
    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
示例#7
0
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
示例#8
0
 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
示例#9
0
 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()
示例#10
0
    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)
示例#11
0
 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()
示例#12
0
 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()
示例#13
0
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
示例#14
0
文件: metadata.py 项目: Eksmo/calibre
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
示例#15
0
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)
示例#16
0
文件: draw.py 项目: 089git/calibre
 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
示例#17
0
文件: draw.py 项目: mrmac123/calibre
 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
示例#18
0
def calibre_cover(title,
                  author_string,
                  series_string=None,
                  output_format='jpg',
                  title_size=46,
                  author_size=36,
                  logo_path=None):
    from calibre.utils.config_base import tweaks
    title = normalize(title)
    author_string = normalize(author_string)
    series_string = normalize(series_string)
    from calibre.utils.magick.draw import create_cover_page, TextLine
    text = title + author_string + (series_string or u'')
    font_path = tweaks['generate_cover_title_font']
    if font_path is None:
        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(title, title_size, font_path=font_path),
        TextLine(author_string, author_size, font_path=font_path)
    ]
    if series_string:
        lines.append(TextLine(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)
示例#19
0
 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 = self.get_metadata()
     self.cover_file = self.opf_file = None
     if self.db is not None:
         self.mi, self.opf_file = create_opf_file(self.db, self.book_id)
         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
示例#20
0
 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 = self.get_metadata()
     self.cover_file = self.opf_file = None
     if self.db is not None:
         self.mi, self.opf_file = create_opf_file(self.db, self.book_id)
         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
示例#21
0
def get_recipe(urls, title):
    fmt = cprefs['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))

    recipe = get_resources('wikipedia.recipe')
    url_line = bytes(repr(urls))
    recipe = re.sub(
        br'^(\s+urls = ).+?# REPLACE_ME_URLS', br'\1' + url_line, recipe,
        flags=re.M)
    if title.strip():
        title_line = bytes(repr(title))
        recipe = re.sub(
            br'^(\s+title\s+=\s+)DEFAULT_TITLE', br'\1' + title_line, recipe,
            flags=re.M)
    logo = get_resources('images/icon.png')
    lf = PersistentTemporaryFile('_wiki_logo.png')
    lf.write(logo)
    recipe = recipe.replace(b'LOGO = None', b'LOGO = %r' % lf.name)
    lf.close()
    rf = PersistentTemporaryFile(suffix='_wikipedia.recipe')
    rf.write(recipe)
    rf.close()
    args = [rf.name, pt.name, recs]
    return args, fmt.upper(), [pt, rf, lf]
示例#22
0
    def extract_content(self, output_dir):
        self.log.info('Extracting PDF...')

        pdf = PersistentTemporaryFile('.pdf')
        pdf.close()
        pdf = open(pdf, 'wb')
        for x in xrange(self.header.section_count()):
            pdf.write(self.header.section_data(x))
        pdf.close()

        from calibre.customize.ui import plugin_for_input_format

        pdf_plugin = plugin_for_input_format('pdf')
        for opt in pdf_plugin.options:
            if not hasattr(self.options, opt.option.name):
                setattr(self.options, opt.option.name, opt.recommended_value)

        return pdf_plugin.convert(open(pdf, 'rb'), self.options, 'pdf', self.log, {})
示例#23
0
 def share(self):
     index = self.available_profiles.currentIndex()
     title, src = self._model.title(index), self._model.script(index)
     if not title or not src:
         error_dialog(self, _('No recipe selected'), _('No recipe selected')).exec_()
         return
     pt = PersistentTemporaryFile(suffix='.recipe')
     pt.write(src.encode('utf-8'))
     pt.close()
     body = _('The attached file: %(fname)s is a '
             'recipe to download %(title)s.')%dict(
                 fname=os.path.basename(pt.name), title=title)
     subject = _('Recipe for ')+title
     url = QUrl('mailto:')
     url.addQueryItem('subject', subject)
     url.addQueryItem('body', body)
     url.addQueryItem('attachment', pt.name)
     open_url(url)
示例#24
0
 def share(self):
     index = self.available_profiles.currentIndex()
     title, src = self._model.title(index), self._model.script(index)
     if not title or not src:
         error_dialog(self, _("No recipe selected"), _("No recipe selected")).exec_()
         return
     pt = PersistentTemporaryFile(suffix=".recipe")
     pt.write(src.encode("utf-8"))
     pt.close()
     body = _("The attached file: %(fname)s is a " "recipe to download %(title)s.") % dict(
         fname=os.path.basename(pt.name), title=title
     )
     subject = _("Recipe for ") + title
     url = QUrl("mailto:")
     url.addQueryItem("subject", subject)
     url.addQueryItem("body", body)
     url.addQueryItem("attachment", pt.name)
     open_url(url)
示例#25
0
def calibre_cover(
    title, author_string, series_string=None, output_format="jpg", title_size=46, author_size=36, logo_path=None
):
    from calibre.utils.config_base import tweaks

    title = normalize(title)
    author_string = normalize(author_string)
    series_string = normalize(series_string)
    from calibre.utils.magick.draw import create_cover_page, TextLine

    text = title + author_string + (series_string or u"")
    font_path = tweaks["generate_cover_title_font"]
    if font_path is None:
        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(title, title_size, font_path=font_path),
        TextLine(author_string, author_size, font_path=font_path),
    ]
    if series_string:
        lines.append(TextLine(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)
示例#26
0
 def paste_image(self):
     c = QApplication.instance().clipboard()
     img = c.image()
     if img.isNull():
         img = c.image(c.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_() == d.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()
示例#27
0
 def files_for_family(self, family, normalize=True):
     '''
     Find all the variants in the font family `family`.
     Returns a dictionary of tuples. Each tuple is of the form (path to font
     file, Full font name).
     The keys of the dictionary depend on `normalize`. If `normalize` is `False`,
     they are a tuple (slant, weight) otherwise they are strings from the set
     `('normal', 'bold', 'italic', 'bi', 'light', 'li')`
     '''
     if iswindows:
         from calibre.ptempfile import PersistentTemporaryFile
         fonts = self.backend.fonts_for_family(family, normalize=normalize)
         ans = {}
         for ft, val in fonts.iteritems():
             ext, name, data = val
             pt = PersistentTemporaryFile('.'+ext)
             pt.write(data)
             pt.close()
             ans[ft] = (pt.name, name)
         return ans
     return self.backend.files_for_family(family, normalize=normalize)
示例#28
0
    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
示例#29
0
def calibre_cover(title, author_string, series_string=None,
        output_format='jpg', title_size=46, author_size=36, logo_path=None):
    from calibre.utils.config_base import tweaks
    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 = tweaks['generate_cover_title_font']
    if font_path is None:
        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)
示例#30
0
    def _download(self, url, filename, save_loc):
        dfilename = ''

        if not url:
            raise Exception(_('No file specified to download.'))
        if not save_loc:
            # Nothing to do.
            return dfilename

        if not filename:
            filename = get_download_filename(url)
            filename, ext = os.path.splitext(filename)
            filename = filename[:60] + ext
            filename = ascii_filename(filename)

        br = browser()
        with closing(br.open(url)) as r:
            tf = PersistentTemporaryFile(suffix=filename)
            tf.write(r.read())
            dfilename = tf.name

        return dfilename
示例#31
0
    def _download(self, url, filename, save_loc):
        dfilename = ''

        if not url:
            raise Exception(_('No file specified to download.'))
        if not save_loc:
            # Nothing to do.
            return dfilename

        if not filename:
            filename = get_download_filename(url)
            filename, ext = os.path.splitext(filename)
            filename = filename[:60] + ext
            filename = ascii_filename(filename)

        br = browser()
        with closing(br.open(url)) as r:
            tf = PersistentTemporaryFile(suffix=filename)
            tf.write(r.read())
            dfilename = tf.name

        return dfilename
示例#32
0
文件: rar.py 项目: yeyanchao/calibre
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",
                "azw1",
                "azw3",
            ):
                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")
示例#33
0
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
示例#34
0
            except:
                pass

            if self.opts.use_existing_cover and not existing_cover:
                log.warning("no existing catalog cover found")

            if self.opts.use_existing_cover and existing_cover:
                recommendations.append(
                    ('cover', cpath, OptionRecommendation.HIGH))
                log.info("using existing catalog cover")
            else:
                log.info("replacing catalog cover")
                new_cover_path = PersistentTemporaryFile(suffix='.jpg')
                new_cover = calibre_cover(
                    opts.catalog_title.replace('"', '\\"'), 'calibre')
                new_cover_path.write(new_cover)
                new_cover_path.close()
                recommendations.append(
                    ('cover', new_cover_path.name, OptionRecommendation.HIGH))

            # Run ebook-convert
            from calibre.ebooks.conversion.plumber import Plumber
            plumber = Plumber(os.path.join(catalog.catalog_path,
                                           opts.basename + '.opf'),
                              path_to_output,
                              log,
                              report_progress=notification,
                              abort_after_input_dump=False)
            plumber.merge_ui_recommendations(recommendations)
            plumber.run()
示例#35
0
def convert_single_ebook(
        parent,
        db,
        book_ids,
        auto_conversion=False,  # {{{
        out_format=None,
        show_no_format_warning=True):
    changed = False
    jobs = []
    bad = []

    total = len(book_ids)
    if total == 0:
        return None, None, None

    for i, book_id in enumerate(book_ids):
        temp_files = []

        try:
            d = SingleConfig(parent, db, book_id, None, out_format)

            if auto_conversion:
                d.accept()
                result = QDialog.Accepted
            else:
                result = d.exec_()

            if result == QDialog.Accepted:
                #if not convert_existing(parent, db, [book_id], d.output_format):
                #    continue

                mi = db.get_metadata(book_id, True)
                in_file = PersistentTemporaryFile('.' + d.input_format)
                with in_file:
                    input_fmt = db.original_fmt(book_id,
                                                d.input_format).lower()
                    same_fmt = input_fmt == d.output_format.lower()
                    db.copy_format_to(book_id,
                                      input_fmt,
                                      in_file,
                                      index_is_id=True)

                out_file = PersistentTemporaryFile('.' + d.output_format)
                out_file.write(d.output_format)
                out_file.close()
                temp_files = [in_file]

                try:
                    dtitle = unicode(mi.title)
                except:
                    dtitle = repr(mi.title)
                desc = _('Convert book %(num)d of %(total)d (%(title)s)') % \
                        {'num':i + 1, 'total':total, 'title':dtitle}

                recs = cPickle.loads(d.recommendations)
                if d.opf_file is not None:
                    recs.append(('read_metadata_from_opf', d.opf_file.name,
                                 OptionRecommendation.HIGH))
                    temp_files.append(d.opf_file)
                if d.cover_file is not None:
                    recs.append(('cover', d.cover_file.name,
                                 OptionRecommendation.HIGH))
                    temp_files.append(d.cover_file)
                args = [in_file.name, out_file.name, recs]
                temp_files.append(out_file)
                func = 'gui_convert_override'
                if same_fmt:
                    func += ':same_fmt'
                jobs.append((func, args, desc, d.output_format.upper(),
                             book_id, temp_files))

                changed = True
                d.break_cycles()
        except NoSupportedInputFormats:
            bad.append(book_id)

    if bad and show_no_format_warning:
        res = []
        for id in bad:
            title = db.title(id, True)
            res.append('%s' % title)

        msg = '%s' % '\n'.join(res)
        warning_dialog(
            parent, _('Could not convert some books'),
            _('Could not convert %(num)d of %(tot)d books, because no suitable source'
              ' format was found.') % dict(num=len(res), tot=total),
            msg).exec_()

    return jobs, changed, bad
示例#36
0
文件: tools.py 项目: ysoffner/calibre
def convert_single_ebook(
        parent,
        db,
        book_ids,
        auto_conversion=False,  # {{{
        out_format=None,
        show_no_format_warning=True):
    changed = False
    jobs = []
    bad = []

    total = len(book_ids)
    if total == 0:
        return None, None, None

    for i, book_id in enumerate(book_ids):
        temp_files = []

        try:
            d = SingleConfig(parent, db, book_id, None, out_format)

            if auto_conversion:
                d.accept()
                result = QDialog.Accepted
            else:
                result = d.exec_()

            if result == QDialog.Accepted:
                # if not convert_existing(parent, db, [book_id], d.output_format):
                #    continue

                mi = db.get_metadata(book_id, True)
                in_file = PersistentTemporaryFile('.' + d.input_format)
                with in_file:
                    input_fmt = db.original_fmt(book_id,
                                                d.input_format).lower()
                    same_fmt = input_fmt == d.output_format.lower()
                    db.copy_format_to(book_id,
                                      input_fmt,
                                      in_file,
                                      index_is_id=True)

                out_file = PersistentTemporaryFile('.' + d.output_format)
                out_file.write(d.output_format)
                out_file.close()
                temp_files = [in_file]

                try:
                    dtitle = unicode(mi.title)
                except:
                    dtitle = repr(mi.title)
                desc = _('Convert book %(num)d of %(total)d (%(title)s)') % \
                        {'num':i + 1, 'total':total, 'title':dtitle}

                recs = cPickle.loads(d.recommendations)
                if d.opf_file is not None:
                    recs.append(('read_metadata_from_opf', d.opf_file.name,
                                 OptionRecommendation.HIGH))
                    temp_files.append(d.opf_file)
                if d.cover_file is not None:
                    recs.append(('cover', d.cover_file.name,
                                 OptionRecommendation.HIGH))
                    temp_files.append(d.cover_file)
                args = [in_file.name, out_file.name, recs]
                temp_files.append(out_file)
                func = 'gui_convert_override'
                parts = []
                if not auto_conversion and d.manually_fine_tune_toc:
                    parts.append('manually_fine_tune_toc')
                if same_fmt:
                    parts.append('same_fmt')
                if parts:
                    func += ':%s' % (';'.join(parts))
                jobs.append((func, args, desc, d.output_format.upper(),
                             book_id, temp_files))

                changed = True
                d.break_cycles()
        except NoSupportedInputFormats as nsif:
            bad.append((book_id, nsif.available_formats))

    if bad and show_no_format_warning:
        if len(bad) == 1 and not bad[0][1]:
            title = db.title(bad[0][0], True)
            warning_dialog(
                parent,
                _('Could not convert'),
                '<p>' +
                _('Could not convert <b>%s</b> as it has no e-book files. If you '
                  'think it should have files, but calibre is not finding '
                  'them, that is most likely because you moved the book\'s '
                  'files around outside of calibre. You will need to find those files '
                  'and re-add them to calibre.') % title,
                show=True)
        else:
            res = []
            for id, available_formats in bad:
                title = db.title(id, True)
                if available_formats:
                    msg = _('No supported formats (Available formats: %s)') % (
                        ', '.join(available_formats))
                else:
                    msg = _('This book has no actual e-book files')
                res.append('%s - %s' % (title, msg))

            msg = '%s' % '\n'.join(res)
            warning_dialog(
                parent, _('Could not convert some books'),
                ngettext(
                    'Could not convert the book because no supported source format was found',
                    'Could not convert {num} of {tot} books, because no supported source formats were found.',
                    len(res)).format(num=len(res), tot=total), msg).exec_()

    return jobs, changed, bad
示例#37
0
文件: tools.py 项目: ysoffner/calibre
    def do_book(self):
        if self.i >= len(self.book_ids):
            return self.do_queue()
        book_id = self.book_ids[self.i]
        self.i += 1

        temp_files = []

        try:
            input_format = get_input_format_for_book(self.db, book_id, None)[0]
            input_fmt = self.db.original_fmt(book_id, input_format).lower()
            same_fmt = input_fmt == self.output_format.lower()
            mi, opf_file = create_opf_file(self.db, book_id)
            in_file = PersistentTemporaryFile('.' + input_format)
            with in_file:
                self.db.copy_format_to(book_id,
                                       input_fmt,
                                       in_file,
                                       index_is_id=True)

            out_file = PersistentTemporaryFile('.' + self.output_format)
            out_file.write(self.output_format)
            out_file.close()
            temp_files = [in_file]

            combined_recs = GuiRecommendations()
            default_recs = bulk_defaults_for_input_format(input_format)
            for key in default_recs:
                combined_recs[key] = default_recs[key]
            if self.use_saved_single_settings:
                specific_recs = load_specifics(self.db, book_id)
                for key in specific_recs:
                    combined_recs[key] = specific_recs[key]
            for item in self.user_recs:
                combined_recs[item[0]] = item[1]
            save_specifics(self.db, book_id, combined_recs)
            lrecs = list(combined_recs.to_recommendations())
            from calibre.customize.ui import plugin_for_output_format
            op = plugin_for_output_format(self.output_format)
            if op and op.recommendations:
                prec = {x[0] for x in op.recommendations}
                for i, r in enumerate(list(lrecs)):
                    if r[0] in prec:
                        lrecs[i] = (r[0], r[1], OptionRecommendation.HIGH)

            cover_file = create_cover_file(self.db, book_id)

            if opf_file is not None:
                lrecs.append(('read_metadata_from_opf', opf_file.name,
                              OptionRecommendation.HIGH))
                temp_files.append(opf_file)
            if cover_file is not None:
                lrecs.append(
                    ('cover', cover_file.name, OptionRecommendation.HIGH))
                temp_files.append(cover_file)

            for x in list(lrecs):
                if x[0] == 'debug_pipeline':
                    lrecs.remove(x)
            try:
                dtitle = unicode(mi.title)
            except:
                dtitle = repr(mi.title)
            if len(dtitle) > 50:
                dtitle = dtitle[:50].rpartition(' ')[0] + '...'
            self.setLabelText(_('Queueing ') + dtitle)
            desc = _('Convert book %(num)d of %(tot)d (%(title)s)') % dict(
                num=self.i, tot=len(self.book_ids), title=dtitle)

            args = [in_file.name, out_file.name, lrecs]
            temp_files.append(out_file)
            func = 'gui_convert_override'
            if same_fmt:
                func += ':same_fmt'
            self.jobs.append((func, args, desc, self.output_format.upper(),
                              book_id, temp_files))

            self.changed = True
            self.setValue(self.i)
        except NoSupportedInputFormats:
            self.bad.append(book_id)
        QTimer.singleShot(0, self.do_book)
示例#38
0
def modify_epub(container, filename, metadata=None, opts={}):
    print(str(opts))
    # Search for the ePub cover
    found_cover = False
    opf = container.opf
    cover_meta_node = opf.xpath('./opf:metadata/opf:meta[@name="cover"]',
                                namespaces=OPF_NAMESPACES)
    if len(cover_meta_node) > 0:
        cover_meta_node = cover_meta_node[0]
        cover_id = cover_meta_node.attrib[
            "content"] if "content" in cover_meta_node.attrib else None
        if cover_id is not None:
            print(
                "KoboTouchExtended:common:modify_epub:Found cover image ID '{0}'"
                .format(cover_id))
            cover_node = opf.xpath(
                './opf:manifest/opf:item[@id="{0}"]'.format(cover_id),
                namespaces=OPF_NAMESPACES)
            if len(cover_node) > 0:
                cover_node = cover_node[0]
                if "properties" not in cover_node.attrib or cover_node.attrib[
                        "properties"] != "cover-image":
                    print(
                        "KoboTouchExtended:common:modify_epub:Setting cover-image property"
                    )
                    cover_node.set("properties", "cover-image")
                    container.dirty(container.opf_name)
                    found_cover = True
    # It's possible that the cover image can't be detected this way. Try looking for the cover image ID in the OPF manifest.
    if not found_cover:
        print(
            "KoboTouchExtended:common:modify_epub:Looking for cover image in OPF manifest"
        )
        node_list = opf.xpath(
            './opf:manifest/opf:item[(@id="cover" or starts-with(@id, "cover")) and starts-with(@media-type, "image")]',
            namespaces=OPF_NAMESPACES)
        if len(node_list) > 0:
            node = node_list[0]
            if "properties" not in node.attrib or node.attrib[
                    "properties"] != 'cover-image':
                print(
                    "KoboTouchExtended:common:modify_epub:Setting cover-image")
                node.set("properties", "cover-image")
                container.dirty(container.opf_name)
                found_cover = True

    # Because of the changes made to the markup here, cleanup needs to be done before any other content file processing
    container.forced_cleanup()
    if 'clean_markup' in opts and opts['clean_markup'] is True:
        container.clean_markup()

    # Hyphenate files?
    if 'hyphenate' in opts and opts['hyphenate'] is True:
        if ('replace_lang' not in opts or opts['replace_lang']
                is not True) or (metadata is not None and metadata.language
                                 == NULL_VALUES['language']):
            print(
                "KoboTouchExtended:common:modify_epub:WARNING - Hyphenation is enabled but not overriding content file language. Hyphenation may use the wrong dictionary."
            )
        hyphenation_css = PersistentTemporaryFile(suffix='_hyphenate',
                                                  prefix='kepub_')
        hyphenation_css.write(get_resources('css/hyphenation.css'))
        hyphenation_css.close()
        css_path = os.path.basename(
            container.copy_file_to_container(hyphenation_css.name,
                                             name='kte-css/hyphenation.css'))
        container.add_content_file_reference("kte-css/{0}".format(css_path))

    # Override content file language
    if 'replace_lang' in opts and opts['replace_lang'] is True and (
            metadata is not None
            and metadata.language != NULL_VALUES["language"]):
        # First override for the OPF file
        lang_node = container.opf_xpath('//opf:metadata/dc:language')
        if len(lang_node) > 0:
            print(
                "KoboTouchExtended:common:modify_epub:Overriding OPF language")
            lang_node = lang_node[0]
            lang_node.text = metadata.language
        else:
            print("KoboTouchExtended:common:modify_epub:Setting OPF language")
            metadata_node = container.opf_xpath('//opf:metadata')[0]
            lang_node = metadata_node.makeelement("{%s}language" %
                                                  OPF_NAMESPACES['dc'])
            lang_node.text = metadata.language
            container.insert_into_xml(metadata_node, lang_node)
        container.dirty(container.opf_name)

        # Now override for content files
        for name in container.get_html_names():
            print(
                "KoboTouchExtended:common:modify_epub:Overriding content file language :: {0}"
                .format(name))
            root = container.parsed(name)
            root.attrib["{%s}lang" % XML_NAMESPACE] = metadata.language
            root.attrib["lang"] = metadata.language

    # Now smarten punctuation
    if 'smarten_punctuation' in opts and opts['smarten_punctuation'] is True:
        container.smarten_punctuation()

    if 'extended_kepub_features' in opts and opts[
            'extended_kepub_features'] is True:
        if metadata is not None:
            print(
                "KoboTouchExtended:common:modify_epub:Adding extended Kobo features to {0} by {1}"
                .format(metadata.title, ' and '.join(metadata.authors)))
        # Add the Kobo span tags
        container.add_kobo_spans()

        skip_js = False
        # Check to see if there's already a kobo*.js in the ePub
        for name in container.name_path_map:
            if kobo_js_re.match(name):
                skip_js = True
                break
        if not skip_js:
            if os.path.isfile(reference_kepub):
                reference_container = EpubContainer(reference_kepub,
                                                    default_log)
                for name in reference_container.name_path_map:
                    if kobo_js_re.match(name):
                        jsname = container.copy_file_to_container(
                            os.path.join(reference_container.root, name),
                            name='kobo.js')
                        container.add_content_file_reference(jsname)
                        break
    os.unlink(filename)
    container.commit(filename)
示例#39
0
    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
        from shlex import split as shsplit

        # 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(mode='w+')
        custom_CSS.write(unicode(self.css1.toPlainText()))
        custom_CSS.close()
        # Create a temporary file with the list of input files
        file_list = PersistentTemporaryFile(mode='w+')
        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)
        # Additional command-line arguments
        args.extend(shsplit(self.args.text()))

        # 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
        if DEBUG:
            from subprocess import list2cmdline
            line = list2cmdline([command] + args)
            print(_('Command line: %s') % line)
        process.start(command, args)
示例#40
0
    def run(self, path_to_output, opts, db, notification=DummyReporter()):
        from calibre.library.catalogs.epub_mobi_builder import CatalogBuilder
        from calibre.utils.logging import default_log as log
        from calibre.utils.config import JSONConfig

        # If preset specified from the cli, insert stored options from JSON file
        if hasattr(opts, 'preset') and opts.preset:
            available_presets = JSONConfig("catalog_presets")
            if opts.preset not in available_presets:
                if available_presets:
                    print(_('Error: Preset "%s" not found.' % opts.preset))
                    print(_('Stored presets: %s' % ', '.join([p for p in sorted(available_presets.keys())])))
                else:
                    print(_('Error: No stored presets.'))
                return 1

            # Copy the relevant preset values to the opts object
            for item in available_presets[opts.preset]:
                if item not in ['exclusion_rules_tw', 'format', 'prefix_rules_tw']:
                    setattr(opts, item, available_presets[opts.preset][item])

            # Provide an unconnected device
            opts.connected_device = {
                         'is_device_connected': False,
                         'kind': None,
                         'name': None,
                         'save_template': None,
                         'serial': None,
                         'storage': None,
                        }

            # Convert prefix_rules and exclusion_rules from JSON lists to tuples
            prs = []
            for rule in opts.prefix_rules:
                prs.append(tuple(rule))
            opts.prefix_rules = tuple(prs)

            ers = []
            for rule in opts.exclusion_rules:
                ers.append(tuple(rule))
            opts.exclusion_rules = tuple(ers)

        opts.log = log
        opts.fmt = self.fmt = path_to_output.rpartition('.')[2]

        # Add local options
        opts.creator = '%s, %s %s, %s' % (strftime('%A'), strftime('%B'), strftime('%d').lstrip('0'), strftime('%Y'))
        opts.creator_sort_as = '%s %s' % ('calibre', strftime('%Y-%m-%d'))
        opts.connected_kindle = False

        # Finalize output_profile
        op = opts.output_profile
        if op is None:
            op = 'default'

        if opts.connected_device['name'] and 'kindle' in opts.connected_device['name'].lower():
            opts.connected_kindle = True
            if opts.connected_device['serial'] and \
               opts.connected_device['serial'][:4] in ['B004', 'B005']:
                op = "kindle_dx"
            else:
                op = "kindle"

        opts.description_clip = 380 if op.endswith('dx') or 'kindle' not in op else 100
        opts.author_clip = 100 if op.endswith('dx') or 'kindle' not in op else 60
        opts.output_profile = op

        opts.basename = "Catalog"
        opts.cli_environment = not hasattr(opts, 'sync')

        # Hard-wired to always sort descriptions by author, with series after non-series
        opts.sort_descriptions_by_author = True

        build_log = []

        build_log.append(u"%s('%s'): Generating %s %sin %s environment, locale: '%s'" %
            (self.name,
             current_library_name(),
             self.fmt,
             'for %s ' % opts.output_profile if opts.output_profile else '',
             'CLI' if opts.cli_environment else 'GUI',
             calibre_langcode_to_name(canonicalize_lang(get_lang()), localize=False))
             )

        # If exclude_genre is blank, assume user wants all tags as genres
        if opts.exclude_genre.strip() == '':
            # opts.exclude_genre = '\[^.\]'
            # build_log.append(" converting empty exclude_genre to '\[^.\]'")
            opts.exclude_genre = 'a^'
            build_log.append(" converting empty exclude_genre to 'a^'")
        if opts.connected_device['is_device_connected'] and \
           opts.connected_device['kind'] == 'device':
            if opts.connected_device['serial']:
                build_log.append(u" connected_device: '%s' #%s%s " %
                    (opts.connected_device['name'],
                     opts.connected_device['serial'][0:4],
                     'x' * (len(opts.connected_device['serial']) - 4)))
                for storage in opts.connected_device['storage']:
                    if storage:
                        build_log.append(u"  mount point: %s" % storage)
            else:
                build_log.append(u" connected_device: '%s'" % opts.connected_device['name'])
                try:
                    for storage in opts.connected_device['storage']:
                        if storage:
                            build_log.append(u"  mount point: %s" % storage)
                except:
                    build_log.append(u"  (no mount points)")
        else:
            build_log.append(u" connected_device: '%s'" % opts.connected_device['name'])

        opts_dict = vars(opts)
        if opts_dict['ids']:
            build_log.append(" book count: %d" % len(opts_dict['ids']))

        sections_list = []
        if opts.generate_authors:
            sections_list.append('Authors')
        if opts.generate_titles:
            sections_list.append('Titles')
        if opts.generate_series:
            sections_list.append('Series')
        if opts.generate_genres:
            sections_list.append('Genres')
        if opts.generate_recently_added:
            sections_list.append('Recently Added')
        if opts.generate_descriptions:
            sections_list.append('Descriptions')

        if not sections_list:
            if opts.cli_environment:
                opts.log.warn('*** No Section switches specified, enabling all Sections ***')
                opts.generate_authors = True
                opts.generate_titles = True
                opts.generate_series = True
                opts.generate_genres = True
                opts.generate_recently_added = True
                opts.generate_descriptions = True
                sections_list = ['Authors', 'Titles', 'Series', 'Genres', 'Recently Added', 'Descriptions']
            else:
                opts.log.warn('\n*** No enabled Sections, terminating catalog generation ***')
                return ["No Included Sections", "No enabled Sections.\nCheck E-book options tab\n'Included sections'\n"]
        if opts.fmt == 'mobi' and sections_list == ['Descriptions']:
            warning = _("\n*** Adding 'By authors' section required for MOBI output ***")
            opts.log.warn(warning)
            sections_list.insert(0, 'Authors')
            opts.generate_authors = True

        opts.log(u" Sections: %s" % ', '.join(sections_list))
        opts.section_list = sections_list

        # Limit thumb_width to 1.0" - 2.0"
        try:
            if float(opts.thumb_width) < float(self.THUMB_SMALLEST):
                log.warning("coercing thumb_width from '%s' to '%s'" % (opts.thumb_width, self.THUMB_SMALLEST))
                opts.thumb_width = self.THUMB_SMALLEST
            if float(opts.thumb_width) > float(self.THUMB_LARGEST):
                log.warning("coercing thumb_width from '%s' to '%s'" % (opts.thumb_width, self.THUMB_LARGEST))
                opts.thumb_width = self.THUMB_LARGEST
            opts.thumb_width = "%.2f" % float(opts.thumb_width)
        except:
            log.error("coercing thumb_width from '%s' to '%s'" % (opts.thumb_width, self.THUMB_SMALLEST))
            opts.thumb_width = "1.0"

        # eval prefix_rules if passed from command line
        if type(opts.prefix_rules) is not tuple:
            try:
                opts.prefix_rules = eval(opts.prefix_rules)
            except:
                log.error("malformed --prefix-rules: %s" % opts.prefix_rules)
                raise
            for rule in opts.prefix_rules:
                if len(rule) != 4:
                    log.error("incorrect number of args for --prefix-rules: %s" % repr(rule))

        # eval exclusion_rules if passed from command line
        if type(opts.exclusion_rules) is not tuple:
            try:
                opts.exclusion_rules = eval(opts.exclusion_rules)
            except:
                log.error("malformed --exclusion-rules: %s" % opts.exclusion_rules)
                raise
            for rule in opts.exclusion_rules:
                if len(rule) != 3:
                    log.error("incorrect number of args for --exclusion-rules: %s" % repr(rule))

        # Display opts
        keys = sorted(opts_dict.keys())
        build_log.append(" opts:")
        for key in keys:
            if key in ['catalog_title', 'author_clip', 'connected_kindle', 'creator',
                       'cross_reference_authors', 'description_clip', 'exclude_book_marker',
                       'exclude_genre', 'exclude_tags', 'exclusion_rules', 'fmt',
                       'genre_source_field', 'header_note_source_field', 'merge_comments_rule',
                       'output_profile', 'prefix_rules', 'preset', 'read_book_marker',
                       'search_text', 'sort_by', 'sort_descriptions_by_author', 'sync',
                       'thumb_width', 'use_existing_cover', 'wishlist_tag']:
                build_log.append("  %s: %s" % (key, repr(opts_dict[key])))
        if opts.verbose:
            log('\n'.join(line for line in build_log))

        # Capture start_time
        opts.start_time = time.time()

        self.opts = opts

        if opts.verbose:
            log.info(" Begin catalog source generation (%s)" %
                     str(datetime.timedelta(seconds=int(time.time() - opts.start_time))))

        # Launch the Catalog builder
        catalog = CatalogBuilder(db, opts, self, report_progress=notification)

        try:
            catalog.build_sources()
            if opts.verbose:
                log.info(" Completed catalog source generation (%s)\n"  %
                         str(datetime.timedelta(seconds=int(time.time() - opts.start_time))))
        except (AuthorSortMismatchException, EmptyCatalogException) as e:
            log.error(" *** Terminated catalog generation: %s ***" % e)
        except:
            log.error(" unhandled exception in catalog generator")
            raise

        else:
            recommendations = []
            recommendations.append(('remove_fake_margins', False,
                OptionRecommendation.HIGH))
            recommendations.append(('comments', '', OptionRecommendation.HIGH))

            """
            >>> Use to debug generated catalog code before pipeline conversion <<<
            """
            GENERATE_DEBUG_EPUB = False
            if GENERATE_DEBUG_EPUB:
                catalog_debug_path = os.path.join(os.path.expanduser('~'), 'Desktop', 'Catalog debug')
                setattr(opts, 'debug_pipeline', os.path.expanduser(catalog_debug_path))

            dp = getattr(opts, 'debug_pipeline', None)
            if dp is not None:
                recommendations.append(('debug_pipeline', dp,
                    OptionRecommendation.HIGH))

            if opts.output_profile and opts.output_profile.startswith("kindle"):
                recommendations.append(('output_profile', opts.output_profile,
                    OptionRecommendation.HIGH))
                recommendations.append(('book_producer', opts.output_profile,
                    OptionRecommendation.HIGH))
                if opts.fmt == 'mobi':
                    recommendations.append(('no_inline_toc', True,
                        OptionRecommendation.HIGH))
                    recommendations.append(('verbose', 2,
                        OptionRecommendation.HIGH))

            # Use existing cover or generate new cover
            cpath = None
            existing_cover = False
            try:
                search_text = 'title:"%s" author:%s' % (
                        opts.catalog_title.replace('"', '\\"'), 'calibre')
                matches = db.search(search_text, return_matches=True, sort_results=False)
                if matches:
                    cpath = db.cover(matches[0], index_is_id=True, as_path=True)
                    if cpath and os.path.exists(cpath):
                        existing_cover = True
            except:
                pass

            if self.opts.use_existing_cover and not existing_cover:
                log.warning("no existing catalog cover found")

            if self.opts.use_existing_cover and existing_cover:
                recommendations.append(('cover', cpath, OptionRecommendation.HIGH))
                log.info("using existing catalog cover")
            else:
                from calibre.ebooks.covers import calibre_cover2
                log.info("replacing catalog cover")
                new_cover_path = PersistentTemporaryFile(suffix='.jpg')
                new_cover = calibre_cover2(opts.catalog_title, 'calibre')
                new_cover_path.write(new_cover)
                new_cover_path.close()
                recommendations.append(('cover', new_cover_path.name, OptionRecommendation.HIGH))

            # Run ebook-convert
            from calibre.ebooks.conversion.plumber import Plumber
            plumber = Plumber(os.path.join(catalog.catalog_path, opts.basename + '.opf'),
                            path_to_output, log, report_progress=notification,
                            abort_after_input_dump=False)
            plumber.merge_ui_recommendations(recommendations)
            plumber.run()

            try:
                os.remove(cpath)
            except:
                pass

            if GENERATE_DEBUG_EPUB:
                from calibre.ebooks.epub import initialize_container
                from calibre.ebooks.tweak import zip_rebuilder
                from calibre.utils.zipfile import ZipFile
                input_path = os.path.join(catalog_debug_path, 'input')
                epub_shell = os.path.join(catalog_debug_path, 'epub_shell.zip')
                initialize_container(epub_shell, opf_name='content.opf')
                with ZipFile(epub_shell, 'r') as zf:
                    zf.extractall(path=input_path)
                os.remove(epub_shell)
                zip_rebuilder(input_path, os.path.join(catalog_debug_path, 'input.epub'))

            if opts.verbose:
                log.info(" Catalog creation complete (%s)\n" %
                     str(datetime.timedelta(seconds=int(time.time() - opts.start_time))))

        # returns to gui2.actions.catalog:catalog_generated()
        return catalog.error
示例#41
0
文件: tools.py 项目: BobPyron/calibre
def convert_single_ebook(parent, db, book_ids, auto_conversion=False, # {{{
        out_format=None, show_no_format_warning=True):
    changed = False
    jobs = []
    bad = []

    total = len(book_ids)
    if total == 0:
        return None, None, None

    for i, book_id in enumerate(book_ids):
        temp_files = []

        try:
            d = SingleConfig(parent, db, book_id, None, out_format)

            if auto_conversion:
                d.accept()
                result = QDialog.Accepted
            else:
                result = d.exec_()

            if result == QDialog.Accepted:
                #if not convert_existing(parent, db, [book_id], d.output_format):
                #    continue

                mi = db.get_metadata(book_id, True)
                in_file = PersistentTemporaryFile('.'+d.input_format)
                with in_file:
                    input_fmt = db.original_fmt(book_id, d.input_format).lower()
                    same_fmt = input_fmt == d.output_format.lower()
                    db.copy_format_to(book_id, input_fmt, in_file,
                            index_is_id=True)

                out_file = PersistentTemporaryFile('.' + d.output_format)
                out_file.write(d.output_format)
                out_file.close()
                temp_files = [in_file]

                try:
                    dtitle = unicode(mi.title)
                except:
                    dtitle = repr(mi.title)
                desc = _('Convert book %(num)d of %(total)d (%(title)s)') % \
                        {'num':i + 1, 'total':total, 'title':dtitle}

                recs = cPickle.loads(d.recommendations)
                if d.opf_file is not None:
                    recs.append(('read_metadata_from_opf', d.opf_file.name,
                        OptionRecommendation.HIGH))
                    temp_files.append(d.opf_file)
                if d.cover_file is not None:
                    recs.append(('cover', d.cover_file.name,
                        OptionRecommendation.HIGH))
                    temp_files.append(d.cover_file)
                args = [in_file.name, out_file.name, recs]
                temp_files.append(out_file)
                func = 'gui_convert_override'
                parts = []
                if not auto_conversion and d.manually_fine_tune_toc:
                    parts.append('manually_fine_tune_toc')
                if same_fmt:
                    parts.append('same_fmt')
                if parts:
                    func += ':%s'%(';'.join(parts))
                jobs.append((func, args, desc, d.output_format.upper(), book_id, temp_files))

                changed = True
                d.break_cycles()
        except NoSupportedInputFormats as nsif:
            bad.append((book_id, nsif.available_formats))

    if bad and show_no_format_warning:
        if len(bad) == 1 and not bad[0][1]:
            title = db.title(bad[0][0], True)
            warning_dialog(parent, _('Could not convert'), '<p>'+
                _('Could not convert <b>%s</b> as it has no ebook files. If you '
                  'think it should have files, but calibre is not finding '
                  'them, that is most likely because you moved the book\'s '
                  'files around outside of calibre. You will need to find those files '
                  'and re-add them to calibre.')%title, show=True)
        else:
            res = []
            for id, available_formats in bad:
                title = db.title(id, True)
                if available_formats:
                    msg = _('No supported formats (Available formats: %s)')%(
                        ', '.join(available_formats))
                else:
                    msg = _('This book has no actual ebook files')
                res.append('%s - %s'%(title, msg))


            msg = '%s' % '\n'.join(res)
            warning_dialog(parent, _('Could not convert some books'),
                _('Could not convert %(num)d of %(tot)d books, because no supported source'
                ' formats were found.') % dict(num=len(res), tot=total),
                msg).exec_()

    return jobs, changed, bad
示例#42
0
文件: tools.py 项目: BobPyron/calibre
    def do_book(self):
        if self.i >= len(self.book_ids):
            return self.do_queue()
        book_id = self.book_ids[self.i]
        self.i += 1

        temp_files = []

        try:
            input_format = get_input_format_for_book(self.db, book_id, None)[0]
            input_fmt = self.db.original_fmt(book_id, input_format).lower()
            same_fmt = input_fmt == self.output_format.lower()
            mi, opf_file = create_opf_file(self.db, book_id)
            in_file = PersistentTemporaryFile('.'+input_format)
            with in_file:
                self.db.copy_format_to(book_id, input_fmt, in_file,
                        index_is_id=True)

            out_file = PersistentTemporaryFile('.' + self.output_format)
            out_file.write(self.output_format)
            out_file.close()
            temp_files = [in_file]

            combined_recs = GuiRecommendations()
            default_recs = bulk_defaults_for_input_format(input_format)
            for key in default_recs:
                combined_recs[key] = default_recs[key]
            if self.use_saved_single_settings:
                specific_recs = load_specifics(self.db, book_id)
                for key in specific_recs:
                    combined_recs[key] = specific_recs[key]
            for item in self.user_recs:
                combined_recs[item[0]] = item[1]
            save_specifics(self.db, book_id, combined_recs)
            lrecs = list(combined_recs.to_recommendations())

            cover_file = create_cover_file(self.db, book_id)

            if opf_file is not None:
                lrecs.append(('read_metadata_from_opf', opf_file.name,
                    OptionRecommendation.HIGH))
                temp_files.append(opf_file)
            if cover_file is not None:
                lrecs.append(('cover', cover_file.name,
                    OptionRecommendation.HIGH))
                temp_files.append(cover_file)

            for x in list(lrecs):
                if x[0] == 'debug_pipeline':
                    lrecs.remove(x)
            try:
                dtitle = unicode(mi.title)
            except:
                dtitle = repr(mi.title)
            if len(dtitle) > 50:
                dtitle = dtitle[:50].rpartition(' ')[0]+'...'
            self.setLabelText(_('Queueing ')+dtitle)
            desc = _('Convert book %(num)d of %(tot)d (%(title)s)') % dict(
                    num=self.i, tot=len(self.book_ids), title=dtitle)

            args = [in_file.name, out_file.name, lrecs]
            temp_files.append(out_file)
            func = 'gui_convert_override'
            if same_fmt:
                func += ':same_fmt'
            self.jobs.append((func, args, desc, self.output_format.upper(), book_id, temp_files))

            self.changed = True
            self.setValue(self.i)
        except NoSupportedInputFormats:
            self.bad.append(book_id)
        QTimer.singleShot(0, self.do_book)
示例#43
0
def convert_single_ebook(parent, db, book_ids, auto_conversion=False, # {{{
        out_format=None, show_no_format_warning=True):
    changed = False
    jobs = []
    bad = []

    total = len(book_ids)
    if total == 0:
        return None, None, None

    for i, book_id in enumerate(book_ids):
        temp_files = []

        try:
            d = SingleConfig(parent, db, book_id, None, out_format)

            if auto_conversion:
                d.accept()
                result = QDialog.Accepted
            else:
                result = d.exec_()

            if result == QDialog.Accepted:
                #if not convert_existing(parent, db, [book_id], d.output_format):
                #    continue

                mi = db.get_metadata(book_id, True)
                in_file = PersistentTemporaryFile('.'+d.input_format)
                with in_file:
                    input_fmt = db.original_fmt(book_id, d.input_format).lower()
                    same_fmt = input_fmt == d.output_format.lower()
                    db.copy_format_to(book_id, input_fmt, in_file,
                            index_is_id=True)

                out_file = PersistentTemporaryFile('.' + d.output_format)
                out_file.write(d.output_format)
                out_file.close()
                temp_files = [in_file]

                try:
                    dtitle = unicode(mi.title)
                except:
                    dtitle = repr(mi.title)
                desc = _('Convert book %(num)d of %(total)d (%(title)s)') % \
                        {'num':i + 1, 'total':total, 'title':dtitle}

                recs = cPickle.loads(d.recommendations)
                if d.opf_file is not None:
                    recs.append(('read_metadata_from_opf', d.opf_file.name,
                        OptionRecommendation.HIGH))
                    temp_files.append(d.opf_file)
                if d.cover_file is not None:
                    recs.append(('cover', d.cover_file.name,
                        OptionRecommendation.HIGH))
                    temp_files.append(d.cover_file)
                args = [in_file.name, out_file.name, recs]
                temp_files.append(out_file)
                func = 'gui_convert_override'
                if same_fmt:
                    func += ':same_fmt'
                jobs.append((func, args, desc, d.output_format.upper(), book_id, temp_files))

                changed = True
                d.break_cycles()
        except NoSupportedInputFormats:
            bad.append(book_id)

    if bad and show_no_format_warning:
        res = []
        for id in bad:
            title = db.title(id, True)
            res.append('%s'%title)

        msg = '%s' % '\n'.join(res)
        warning_dialog(parent, _('Could not convert some books'),
            _('Could not convert %(num)d of %(tot)d books, because no suitable source'
               ' format was found.') % dict(num=len(res), tot=total),
            msg).exec_()

    return jobs, changed, bad
示例#44
0
def modify_epub(
        container,  # type: EpubContainer
        filename,  # type: str
        metadata=None,  # type: Optional[Metadata]
        opts={},  # type: Dict[str, Union[str, bool]]
):  # type: (...) -> None
    """Modify the ePub file to make it KePub-compliant."""
    _modify_start = time.time()

    # Search for the ePub cover
    # TODO: Refactor out cover detection logic so it can be directly used in
    # metadata/writer.py
    found_cover = False  # type: bool
    opf = container.opf  # type: _Element
    cover_meta_node_list = opf.xpath(
        './opf:metadata/opf:meta[@name="cover"]',
        namespaces=OPF_NAMESPACES)  # List[_Element]

    if len(cover_meta_node_list) > 0:
        cover_meta_node = cover_meta_node_list[0]  # type: _Element
        cover_id = cover_meta_node.attrib.get("content", None)

        log.debug("Found meta node with name=cover")

        if cover_id:
            log.info("Found cover image ID '{0}'".format(cover_id))

            cover_node_list = opf.xpath(
                './opf:manifest/opf:item[@id="{0}"]'.format(cover_id),
                namespaces=OPF_NAMESPACES,
            )  # type: List[_Element]
            if len(cover_node_list) > 0:
                cover_node = cover_node_list[0]  # type: _Element

                log.debug("Found an item node with cover ID")

                if cover_node.attrib.get("properties", "") != "cover-image":
                    log.info("Setting cover-image property")
                    cover_node.set("properties", "cover-image")
                    container.dirty(container.opf_name)
                else:
                    log.warning("Item node is already set as cover-image")
                found_cover = True

    # It's possible that the cover image can't be detected this way. Try
    # looking for the cover image ID in the OPF manifest.
    if not found_cover:
        log.debug("Looking for cover image in OPF manifest")

        node_list = opf.xpath(
            "./opf:manifest/opf:item[(translate(@id, " +
            "'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')" +
            '="cover" or starts-with(translate(@id, ' +
            "'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')" +
            ', "cover")) and starts-with(@media-type, "image")]',
            namespaces=OPF_NAMESPACES,
        )  # type: List[_Element]
        if len(node_list) > 0:
            log.info("Found {0:d} nodes, assuming the first is the "
                     "right node".format(len(node_list)))

            node = node_list[0]  # type: _Element
            if node.attrib.get("properties", "") != "cover-image":
                log.info("Setting cover-image property")
                node.set("properties", "cover-image")
                container.dirty(container.opf_name)
            else:
                log.warning("Item node is already set as cover-image")
            found_cover = True

    # Hyphenate files?
    if opts.get("no-hyphens", False):
        nohyphen_css = PersistentTemporaryFile(
            suffix="_nohyphen",
            prefix="kepub_")  # type: PersistentTemporaryFile
        nohyphen_css.write(get_resources("css/no-hyphens.css"))  # noqa: F821
        nohyphen_css.close()

        css_path = os.path.basename(
            container.copy_file_to_container(
                nohyphen_css.name, name="kte-css/no-hyphens.css"))  # type: str
        container.add_content_file_reference("kte-css/{0}".format(css_path))
        os.unlink(nohyphen_css.name)
    elif opts.get("hyphenate", False) and opts.get("hyphen_min_chars", 6) > 0:
        if metadata and metadata.language == NULL_VALUES["language"]:
            log.warning(
                "Hyphenation is enabled but not overriding content file "
                "language. Hyphenation may use the wrong dictionary.")
        hyphen_css = PersistentTemporaryFile(
            suffix="_hyphenate",
            prefix="kepub_")  # type: PersistentTemporaryFile
        css_template = get_resources(
            "css/hyphenation.css.tmpl").decode()  # noqa: F821
        hyphen_limit_lines = opts.get("hyphen_limit_lines", 2)
        if hyphen_limit_lines == 0:
            hyphen_limit_lines = "no-limit"
        hyphen_css.write(
            css_template.format(
                hyphen_min_chars=opts.get("hyphen_min_chars"),
                hyphen_min_chars_before=opts.get("hyphen_min_chars_before", 3),
                hyphen_min_chars_after=opts.get("hyphen_min_chars_after", 3),
                hyphen_limit_lines=hyphen_limit_lines,
            ).encode())
        hyphen_css.close()

        css_path = os.path.basename(
            container.copy_file_to_container(
                hyphen_css.name, name="kte-css/hyphenation.css"))  # type: str
        container.add_content_file_reference("kte-css/{0}".format(css_path))
        os.unlink(hyphen_css.name)

    # Now smarten punctuation
    if opts.get("smarten_punctuation", False):
        container.smarten_punctuation()

    if opts.get("extended_kepub_features", True):
        if metadata is not None:
            log.info("Adding extended Kobo features to {0} by {1}".format(
                metadata.title, " and ".join(metadata.authors)))

        # Add the Kobo span and div tags
        container.convert()

        # Check to see if there's already a kobo*.js in the ePub
        skip_js = False  # type: str
        for name in container.name_path_map:
            if KOBO_JS_RE.match(name):
                skip_js = True
                break

        if not skip_js:
            if os.path.isfile(REFERENCE_KEPUB):
                reference_container = EpubContainer(REFERENCE_KEPUB, log)
                for name in reference_container.name_path_map:
                    if KOBO_JS_RE.match(name):
                        jsname = container.copy_file_to_container(
                            os.path.join(reference_container.root, name),
                            name="kobo.js")
                        container.add_content_file_reference(jsname)
                        break

        # Add the Kobo style hacks
        stylehacks_css = PersistentTemporaryFile(suffix="_stylehacks",
                                                 prefix="kepub_")
        stylehacks_css.write(
            get_resources("css/style-hacks.css"))  # noqa: F821
        stylehacks_css.close()

        css_path = os.path.basename(
            container.copy_file_to_container(stylehacks_css.name,
                                             name="kte-css/stylehacks.css"))
        container.add_content_file_reference("kte-css/{0}".format(css_path))
    os.unlink(filename)
    container.commit(filename)

    _modify_time = time.time() - _modify_start
    log.info("modify_epub took {0:f} seconds".format(_modify_time))
示例#45
0
                    if cpath and os.path.exists(cpath):
                        existing_cover = True
            except:
                pass

            if self.opts.use_existing_cover and not existing_cover:
                log.warning("no existing catalog cover found")

            if self.opts.use_existing_cover and existing_cover:
                recommendations.append(('cover', cpath, OptionRecommendation.HIGH))
                log.info("using existing catalog cover")
            else:
                log.info("replacing catalog cover")
                new_cover_path = PersistentTemporaryFile(suffix='.jpg')
                new_cover = calibre_cover(opts.catalog_title.replace('"', '\\"'), 'calibre')
                new_cover_path.write(new_cover)
                new_cover_path.close()
                recommendations.append(('cover', new_cover_path.name, OptionRecommendation.HIGH))

            # Run ebook-convert
            from calibre.ebooks.conversion.plumber import Plumber
            plumber = Plumber(os.path.join(catalog.catalog_path, opts.basename + '.opf'),
                            path_to_output, log, report_progress=notification,
                            abort_after_input_dump=False)
            plumber.merge_ui_recommendations(recommendations)
            plumber.run()

            try:
                os.remove(cpath)
            except:
                pass