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 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.utils.lock import ExclusiveFile
from calibre import sanitize_file_name from calibre import sanitize_file_name
from calibre.customize.conversion import OptionRecommendation from calibre.customize.conversion import OptionRecommendation
from calibre.customize.ui import available_output_formats
config_dir = os.path.join(config_dir, 'conversion') config_dir = os.path.join(config_dir, 'conversion')
@ -114,3 +115,78 @@ class GuiRecommendations(dict):
self.disabled_options.add(name) self.disabled_options.add(name)
elif opt.level > level or name not in self: elif opt.level > level or name not in self:
self[name] = opt.recommended_value 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 PyQt5.Qt import QModelIndex, QDialog
from calibre.gui2.convert.single import (Config, sort_formats_by_preference, from calibre.gui2.convert.single import Config, GroupModel, gprefs
GroupModel, gprefs, get_output_formats)
from calibre.gui2.convert.look_and_feel import LookAndFeelWidget from calibre.gui2.convert.look_and_feel import LookAndFeelWidget
from calibre.gui2.convert.heuristics import HeuristicsWidget from calibre.gui2.convert.heuristics import HeuristicsWidget
from calibre.gui2.convert.search_and_replace import SearchAndReplaceWidget 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.toc import TOCWidget
from calibre.gui2.convert import GuiRecommendations from calibre.gui2.convert import GuiRecommendations
from calibre.ebooks.conversion.plumber import Plumber 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.config import prefs
from calibre.utils.logging import Log 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 PyQt5.Qt import QAbstractListModel, Qt, QFont, QModelIndex, QDialog, QCoreApplication, QSize
from calibre.gui2 import gprefs from calibre.gui2 import gprefs
from calibre.ebooks.conversion.config import (GuiRecommendations, save_specifics, from calibre.ebooks.conversion.config import (
load_specifics) 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.single_ui import Ui_Dialog
from calibre.gui2.convert.metadata import MetadataWidget from calibre.gui2.convert.metadata import MetadataWidget
from calibre.gui2.convert.look_and_feel import LookAndFeelWidget 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.gui2.convert.debug import DebugWidget
from calibre.ebooks.conversion.plumber import (Plumber, from calibre.ebooks.conversion.plumber import (Plumber, ARCHIVE_FMTS)
supported_input_formats, ARCHIVE_FMTS)
from calibre.ebooks.conversion.config import delete_specifics from calibre.ebooks.conversion.config import delete_specifics
from calibre.customize.ui import available_output_formats
from calibre.customize.conversion import OptionRecommendation 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 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): class GroupModel(QAbstractListModel):
def __init__(self, widgets): def __init__(self, widgets):
@ -92,49 +56,6 @@ class GroupModel(QAbstractListModel):
return None 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): class Config(QDialog, Ui_Dialog):
''' '''
Configuration dialog for single book conversion. If accepted, has the 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.ptempfile import PersistentTemporaryFile
from calibre.gui2 import warning_dialog, question_dialog from calibre.gui2 import warning_dialog, question_dialog
from calibre.gui2.convert.single import NoSupportedInputFormats from calibre.gui2.convert.single import Config as SingleConfig
from calibre.gui2.convert.single import Config as SingleConfig, \
get_input_format_for_book
from calibre.gui2.convert.bulk import BulkConfig from calibre.gui2.convert.bulk import BulkConfig
from calibre.gui2.convert.metadata import create_opf_file, create_cover_file from calibre.gui2.convert.metadata import create_opf_file, create_cover_file
from calibre.customize.conversion import OptionRecommendation from calibre.customize.conversion import OptionRecommendation
from calibre.utils.config import prefs from calibre.utils.config import prefs
from calibre.ebooks.conversion.config import GuiRecommendations, \ from calibre.ebooks.conversion.config import (
load_defaults, load_specifics, save_specifics GuiRecommendations, load_defaults, load_specifics, save_specifics,
get_input_format_for_book, NoSupportedInputFormats)
from calibre.gui2.convert import bulk_defaults_for_input_format 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 bad and show_no_format_warning:
if len(bad) == 1 and not bad[0][1]: if len(bad) == 1 and not bad[0][1]:
title = db.title(bad[0][0], True) title = db.title(bad[0][0], True)
warning_dialog(parent, _('Could not convert'), '<p>'+ warning_dialog(parent, _('Could not convert'), '<p>'+ _(
_('Could not convert <b>%s</b> as it has no e-book files. If you ' '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 ' 'think it should have files, but calibre is not finding '
'them, that is most likely because you moved the book\'s ' 'them, that is most likely because you moved the book\'s '
'files around outside of calibre. You will need to find those files ' 'files around outside of calibre. You will need to find those files '
'and re-add them to calibre.')%title, show=True) 'and re-add them to calibre.')%title, show=True)
else: else:
res = [] res = []
for id, available_formats in bad: for id, available_formats in bad: