Refactor code to get conversion formats to make it re-useable

This commit is contained in:
Kovid Goyal 2018-06-20 10:32:55 +05:30
parent 91dcd80f8c
commit 27c79db06a
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 93 additions and 97 deletions

View File

@ -8,10 +8,11 @@ __docformat__ = 'restructuredtext en'
import os, ast, json
from calibre.utils.config import config_dir
from calibre.utils.config import config_dir, prefs, tweaks
from calibre.utils.lock import ExclusiveFile
from calibre import sanitize_file_name
from calibre.customize.conversion import OptionRecommendation
from calibre.customize.ui import available_output_formats
config_dir = os.path.join(config_dir, 'conversion')
@ -114,3 +115,78 @@ class GuiRecommendations(dict):
self.disabled_options.add(name)
elif opt.level > level or name not in self:
self[name] = opt.recommended_value
def get_available_formats_for_book(db, book_id):
available_formats = db.new_api.formats(book_id)
return {x.lower() for x in available_formats}
class NoSupportedInputFormats(Exception):
def __init__(self, available_formats):
Exception.__init__(self)
self.available_formats = available_formats
def get_supported_input_formats_for_book(db, book_id):
from calibre.ebooks.conversion.plumber import supported_input_formats
available_formats = get_available_formats_for_book(db, book_id)
input_formats = {x.lower() for x in supported_input_formats()}
input_formats = sorted(available_formats.intersection(input_formats))
if not input_formats:
raise NoSupportedInputFormats(tuple(x for x in available_formats if x))
return input_formats
def get_preferred_input_format_for_book(db, book_id):
recs = load_specifics(db, book_id)
if recs:
return recs.get('gui_preferred_input_format', None)
def sort_formats_by_preference(formats, prefs):
uprefs = [x.upper() for x in prefs]
def key(x):
try:
return uprefs.index(x.upper())
except ValueError:
pass
return len(prefs)
return sorted(formats, key=key)
def get_input_format_for_book(db, book_id, pref=None):
'''
Return (preferred input format, list of available formats) for the book
identified by book_id. Raises an error if the book has no input formats.
:param pref: If None, the format used as input for the last conversion, if
any, on this book is used. If not None, should be a lowercase format like
'epub' or 'mobi'. If you do not want the last converted format to be used,
set pref=False.
'''
if pref is None:
pref = get_preferred_input_format_for_book(db, book_id)
if hasattr(pref, 'lower'):
pref = pref.lower()
input_formats = get_supported_input_formats_for_book(db, book_id)
input_format = pref if pref in input_formats else \
sort_formats_by_preference(input_formats, prefs['input_format_order'])[0]
return input_format, input_formats
def get_output_formats(preferred_output_format):
all_formats = {x.upper() for x in available_output_formats()}
all_formats.discard('OEB')
pfo = preferred_output_format.upper() if preferred_output_format else ''
restrict = tweaks['restrict_output_formats']
if restrict:
fmts = [x.upper() for x in restrict]
if pfo and pfo not in fmts and pfo in all_formats:
fmts.append(pfo)
else:
fmts = list(sorted(all_formats,
key=lambda x:{'EPUB':'!A', 'MOBI':'!B'}.get(x.upper(), x)))
return fmts

View File

@ -8,8 +8,7 @@ import shutil
from PyQt5.Qt import QModelIndex, QDialog
from calibre.gui2.convert.single import (Config, sort_formats_by_preference,
GroupModel, gprefs, get_output_formats)
from calibre.gui2.convert.single import Config, GroupModel, gprefs
from calibre.gui2.convert.look_and_feel import LookAndFeelWidget
from calibre.gui2.convert.heuristics import HeuristicsWidget
from calibre.gui2.convert.search_and_replace import SearchAndReplaceWidget
@ -18,6 +17,7 @@ from calibre.gui2.convert.structure_detection import StructureDetectionWidget
from calibre.gui2.convert.toc import TOCWidget
from calibre.gui2.convert import GuiRecommendations
from calibre.ebooks.conversion.plumber import Plumber
from calibre.ebooks.conversion.config import sort_formats_by_preference, get_output_formats
from calibre.utils.config import prefs
from calibre.utils.logging import Log

View File

@ -11,8 +11,8 @@ import cPickle, shutil
from PyQt5.Qt import QAbstractListModel, Qt, QFont, QModelIndex, QDialog, QCoreApplication, QSize
from calibre.gui2 import gprefs
from calibre.ebooks.conversion.config import (GuiRecommendations, save_specifics,
load_specifics)
from calibre.ebooks.conversion.config import (
GuiRecommendations, save_specifics, sort_formats_by_preference, get_input_format_for_book, get_output_formats)
from calibre.gui2.convert.single_ui import Ui_Dialog
from calibre.gui2.convert.metadata import MetadataWidget
from calibre.gui2.convert.look_and_feel import LookAndFeelWidget
@ -24,49 +24,13 @@ from calibre.gui2.convert.toc import TOCWidget
from calibre.gui2.convert.debug import DebugWidget
from calibre.ebooks.conversion.plumber import (Plumber,
supported_input_formats, ARCHIVE_FMTS)
from calibre.ebooks.conversion.plumber import (Plumber, ARCHIVE_FMTS)
from calibre.ebooks.conversion.config import delete_specifics
from calibre.customize.ui import available_output_formats
from calibre.customize.conversion import OptionRecommendation
from calibre.utils.config import prefs, tweaks
from calibre.utils.config import prefs
from calibre.utils.logging import Log
class NoSupportedInputFormats(Exception):
def __init__(self, available_formats):
Exception.__init__(self)
self.available_formats = available_formats
def sort_formats_by_preference(formats, prefs):
uprefs = [x.upper() for x in prefs]
def key(x):
try:
return uprefs.index(x.upper())
except ValueError:
pass
return len(prefs)
return sorted(formats, key=key)
def get_output_formats(preferred_output_format):
all_formats = {x.upper() for x in available_output_formats()}
all_formats.discard('OEB')
pfo = preferred_output_format.upper() if preferred_output_format else ''
restrict = tweaks['restrict_output_formats']
if restrict:
fmts = [x.upper() for x in restrict]
if pfo and pfo not in fmts and pfo in all_formats:
fmts.append(pfo)
else:
fmts = list(sorted(all_formats,
key=lambda x:{'EPUB':'!A', 'MOBI':'!B'}.get(x.upper(), x)))
return fmts
class GroupModel(QAbstractListModel):
def __init__(self, widgets):
@ -92,49 +56,6 @@ class GroupModel(QAbstractListModel):
return None
def get_preferred_input_format_for_book(db, book_id):
recs = load_specifics(db, book_id)
if recs:
return recs.get('gui_preferred_input_format', None)
def get_available_formats_for_book(db, book_id):
available_formats = db.formats(book_id, index_is_id=True)
if not available_formats:
available_formats = ''
return set([x.lower() for x in
available_formats.split(',')])
def get_supported_input_formats_for_book(db, book_id):
available_formats = get_available_formats_for_book(db, book_id)
input_formats = set([x.lower() for x in supported_input_formats()])
input_formats = sorted(available_formats.intersection(input_formats))
if not input_formats:
raise NoSupportedInputFormats(tuple(x for x in available_formats if x))
return input_formats
def get_input_format_for_book(db, book_id, pref):
'''
Return (preferred input format, list of available formats) for the book
identified by book_id. Raises an error if the book has no input formats.
:param pref: If None, the format used as input for the last conversion, if
any, on this book is used. If not None, should be a lowercase format like
'epub' or 'mobi'. If you do not want the last converted format to be used,
set pref=False.
'''
if pref is None:
pref = get_preferred_input_format_for_book(db, book_id)
if hasattr(pref, 'lower'):
pref = pref.lower()
input_formats = get_supported_input_formats_for_book(db, book_id)
input_format = pref if pref in input_formats else \
sort_formats_by_preference(input_formats, prefs['input_format_order'])[0]
return input_format, input_formats
class Config(QDialog, Ui_Dialog):
'''
Configuration dialog for single book conversion. If accepted, has the

View File

@ -13,15 +13,14 @@ from PyQt5.Qt import QDialog, QProgressDialog, QTimer
from calibre.ptempfile import PersistentTemporaryFile
from calibre.gui2 import warning_dialog, question_dialog
from calibre.gui2.convert.single import NoSupportedInputFormats
from calibre.gui2.convert.single import Config as SingleConfig, \
get_input_format_for_book
from calibre.gui2.convert.single import Config as SingleConfig
from calibre.gui2.convert.bulk import BulkConfig
from calibre.gui2.convert.metadata import create_opf_file, create_cover_file
from calibre.customize.conversion import OptionRecommendation
from calibre.utils.config import prefs
from calibre.ebooks.conversion.config import GuiRecommendations, \
load_defaults, load_specifics, save_specifics
from calibre.ebooks.conversion.config import (
GuiRecommendations, load_defaults, load_specifics, save_specifics,
get_input_format_for_book, NoSupportedInputFormats)
from calibre.gui2.convert import bulk_defaults_for_input_format
@ -100,12 +99,12 @@ def convert_single_ebook(parent, db, book_ids, auto_conversion=False, # {{{
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)
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: