This commit is contained in:
Kovid Goyal 2009-03-29 18:26:44 -07:00
parent b9d9df5f20
commit b98ada75f7
7 changed files with 187 additions and 141 deletions

View File

@ -1,6 +1,6 @@
from __future__ import with_statement
'''
Defines the plugin sytem for conversions.
Defines the plugin system for conversions.
'''
import re, os, shutil
@ -236,6 +236,6 @@ class OutputFormatPlugin(Plugin):
#: (option_name, recommended_value, recommendation_level)
recommendations = set([])
def convert(self, oeb_book, input_plugin, options, parse_cache, log):
def convert(self, oeb_book, input_plugin, options, context, log):
raise NotImplementedError

View File

@ -13,6 +13,11 @@ class OptionValues(object):
pass
class Plumber(object):
'''
The `Plumber` manages the conversion pipeline. An UI should call the methods
:method:`merge_ui_recommendations` and then :method:`run`. The plumber will
take care of the rest.
'''
metadata_option_names = [
'title', 'authors', 'title_sort', 'author_sort', 'cover', 'comments',
@ -21,10 +26,17 @@ class Plumber(object):
]
def __init__(self, input, output, log):
'''
:param input: Path to input file.
:param output: Path to output file/directory
'''
self.input = input
self.output = output
self.log = log
# Initialize the conversion options that are independent of input and
# output formats. The input and output plugins can still disable these
# options via recommendations.
self.pipeline_options = [
OptionRecommendation(name='verbose',
@ -143,11 +155,15 @@ OptionRecommendation(name='language',
self.input_fmt = input_fmt
self.output_fmt = output_fmt
# Build set of all possible options. Two options are equal iff their
# names are the same.
self.input_options = self.input_plugin.options.union(
self.input_plugin.common_options)
self.output_options = self.output_plugin.options.union(
self.output_plugin.common_options)
# Remove the options that have been disabled by recommendations from the
# plugins.
self.merge_plugin_recommendations()
def get_option_by_name(self, name):
@ -165,12 +181,21 @@ OptionRecommendation(name='language',
rec.recommended_value = val
def merge_ui_recommendations(self, recommendations):
'''
Merge recommendations from the UI. As long as the UI recommendation
level is >= the baseline recommended level, the UI value is used,
*except* if the baseline has a recommendation level of `HIGH`.
'''
for name, val, level in recommendations:
rec = self.get_option_by_name(name)
if rec is not None and rec.level <= level and rec.level < rec.HIGH:
rec.recommended_value = val
def read_user_metadata(self):
'''
Read all metadata specified by the user. Command line options override
metadata from a specified OPF file.
'''
from calibre.ebooks.metadata import MetaInformation, string_to_authors
from calibre.ebooks.metadata.opf2 import OPF
mi = MetaInformation(None, [])
@ -197,6 +222,9 @@ OptionRecommendation(name='language',
def setup_options(self):
'''
Setup the `self.opts` object.
'''
self.opts = OptionValues()
for group in (self.input_options, self.pipeline_options,
self.output_options):
@ -216,10 +244,18 @@ OptionRecommendation(name='language',
self.read_user_metadata()
def run(self):
'''
Run the conversion pipeline
'''
# Setup baseline option values
self.setup_options()
# Run any preprocess plugins
from calibre.customize.ui import run_plugins_on_preprocess
self.input = run_plugins_on_preprocess(self.input)
# Create an OEBBook from the input file. The input plugin does all the
# heavy lifting.
from calibre.ebooks.oeb.reader import OEBReader
from calibre.ebooks.oeb.base import OEBBook
parse_cache, accelerators = {}, {}
@ -230,6 +266,7 @@ OptionRecommendation(name='language',
self.reader = OEBReader()
self.oeb = OEBBook(self.log, parse_cache=parse_cache)
# Read OEB Book into OEBBook
self.reader(self.oeb, opfpath)

View File

@ -1260,7 +1260,7 @@ class OEBBook(object):
"""Create empty book. Optional arguments:
:param parse_cache: A cache of parsed XHTML/CSS. Keys are absolute
paths to te cached files and values are lxml root objects and
paths to the cached files and values are lxml root objects and
cssutils stylesheets.
:param:`encoding`: Default encoding for textual content read
from an external container.

View File

@ -12,6 +12,6 @@ class OEBOutput(OutputFormatPlugin):
file_type = 'oeb'
def convert(self, oeb_book, input_plugin, options, parse_cache, log):
pass
def convert(self, oeb_book, input_plugin, options, context, log):
pass

View File

@ -0,0 +1,10 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'

View File

@ -24,7 +24,6 @@ class ManifestTrimmer(object):
def __call__(self, oeb, context):
oeb.logger.info('Trimming unused files from manifest...')
used = set()
hrefs = oeb.manifest.hrefs
for term in oeb.metadata:
for item in oeb.metadata[term]:
if item.value in oeb.manifest.hrefs: