Sync to pluginize

This commit is contained in:
John Schember 2009-04-11 22:23:35 -04:00
commit 00f24eaf5d
5 changed files with 93 additions and 63 deletions

View File

@ -30,7 +30,7 @@ def _config():
c.add_opt('filetype_mapping', default={}, help=_('Mapping for filetype plugins'))
c.add_opt('plugin_customization', default={}, help=_('Local plugin customization'))
c.add_opt('disabled_plugins', default=set([]), help=_('Disabled plugins'))
return ConfigProxy(c)
config = _config()
@ -45,7 +45,7 @@ class PluginNotFound(ValueError):
def load_plugin(path_to_zip_file):
'''
Load plugin from zip file or raise InvalidPlugin error
:return: A :class:`Plugin` instance.
'''
print 'Loading plugin from', path_to_zip_file
@ -61,9 +61,9 @@ def load_plugin(path_to_zip_file):
if x.minimum_calibre_version > version or \
platform not in x.supported_platforms:
continue
return x
raise InvalidPlugin(_('No valid plugin found in ')+path_to_zip_file)
_initialized_plugins = []
@ -122,8 +122,8 @@ def reread_metadata_plugins():
for ft in plugin.file_types:
if not _metadata_writers.has_key(ft):
_metadata_writers[ft] = []
_metadata_writers[ft].append(plugin)
_metadata_writers[ft].append(plugin)
def metadata_readers():
ans = set([])
for plugins in _metadata_readers.values():
@ -136,8 +136,8 @@ def metadata_writers():
for plugins in _metadata_writers.values():
for plugin in plugins:
ans.add(plugin)
return ans
return ans
def get_file_type_metadata(stream, ftype):
mi = MetaInformation(None, None)
ftype = ftype.lower().strip()
@ -163,21 +163,21 @@ def set_file_type_metadata(stream, mi, ftype):
plugin.set_metadata(stream, mi, ftype.lower().strip())
break
except:
print 'Failed to set metadata for', repr(getattr(mi, 'title', ''))
print 'Failed to set metadata for', repr(getattr(mi, 'title', ''))
traceback.print_exc()
def _run_filetype_plugins(path_to_file, ft=None, occasion='preprocess'):
occasion = {'import':_on_import, 'preprocess':_on_preprocess,
occasion = {'import':_on_import, 'preprocess':_on_preprocess,
'postprocess':_on_postprocess}[occasion]
customization = config['plugin_customization']
if ft is None:
ft = os.path.splitext(path_to_file)[-1].lower().replace('.', '')
ft = os.path.splitext(path_to_file)[-1].lower().replace('.', '')
nfp = path_to_file
for plugin in occasion.get(ft, []):
if is_disabled(plugin):
continue
plugin.site_customization = customization.get(plugin.name, '')
plugin.site_customization = customization.get(plugin.name, '')
with plugin:
try:
nfp = plugin.run(path_to_file)
@ -190,13 +190,13 @@ def _run_filetype_plugins(path_to_file, ft=None, occasion='preprocess'):
nfp = path_to_file
return nfp
run_plugins_on_import = functools.partial(_run_filetype_plugins,
run_plugins_on_import = functools.partial(_run_filetype_plugins,
occasion='import')
run_plugins_on_preprocess = functools.partial(_run_filetype_plugins,
run_plugins_on_preprocess = functools.partial(_run_filetype_plugins,
occasion='preprocess')
run_plugins_on_postprocess = functools.partial(_run_filetype_plugins,
run_plugins_on_postprocess = functools.partial(_run_filetype_plugins,
occasion='postprocess')
def initialize_plugin(plugin, path_to_zip_file):
try:
@ -206,7 +206,7 @@ def initialize_plugin(plugin, path_to_zip_file):
tb = traceback.format_exc()
raise InvalidPlugin((_('Initialization of plugin %s failed with traceback:')
%tb) + '\n'+tb)
def add_plugin(path_to_zip_file):
make_config_dir()
@ -248,18 +248,18 @@ def input_format_plugins():
for plugin in _initialized_plugins:
if isinstance(plugin, InputFormatPlugin):
yield plugin
def plugin_for_input_format(fmt):
for plugin in input_format_plugins():
if fmt.lower() in plugin.file_types:
return plugin
def available_input_formats():
formats = []
formats = set([])
for plugin in input_format_plugins():
if not is_disabled(plugin):
for format in plugin.file_types:
formats.append(format)
formats.add(format)
return formats
def output_format_plugins():
@ -273,10 +273,10 @@ def plugin_for_output_format(fmt):
return plugin
def available_output_formats():
formats = []
formats = set([])
for plugin in output_format_plugins():
if not is_disabled(plugin):
formats.append(plugin.file_type)
formats.add(plugin.file_type)
return formats
def disable_plugin(plugin_or_name):
@ -309,21 +309,21 @@ def initialize_plugins():
except:
print 'Failed to initialize plugin...'
traceback.print_exc()
_initialized_plugins.sort(cmp=lambda x,y:cmp(x.priority, y.priority), reverse=True)
_initialized_plugins.sort(cmp=lambda x,y:cmp(x.priority, y.priority), reverse=True)
reread_filetype_plugins()
reread_metadata_plugins()
initialize_plugins()
def option_parser():
parser = OptionParser(usage=_('''\
%prog options
Customize calibre by loading external plugins.
'''))
parser.add_option('-a', '--add-plugin', default=None,
parser.add_option('-a', '--add-plugin', default=None,
help=_('Add a plugin by specifying the path to the zip file containing it.'))
parser.add_option('-r', '--remove-plugin', default=None,
parser.add_option('-r', '--remove-plugin', default=None,
help=_('Remove a custom plugin by name. Has no effect on builtin plugins'))
parser.add_option('--customize-plugin', default=None,
help=_('Customize plugin. Specify name of plugin and customization string separated by a comma.'))
@ -377,16 +377,16 @@ def main(args=sys.argv):
print
for plugin in initialized_plugins():
print fmt%(
plugin.type, plugin.name,
plugin.version, is_disabled(plugin),
plugin.type, plugin.name,
plugin.version, is_disabled(plugin),
plugin_customization(plugin)
)
print '\t', plugin.description
if plugin.is_customizable():
print '\t', plugin.customization_help()
print
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@ -179,10 +179,13 @@ OptionRecommendation(name='language',
raise ValueError('Input file must have an extension')
input_fmt = input_fmt[1:].lower()
output_fmt = os.path.splitext(output)[1]
if not output_fmt:
output_fmt = '.oeb'
output_fmt = output_fmt[1:].lower()
if os.path.exists(output) and os.path.isdir(output):
output_fmt = 'oeb'
else:
output_fmt = os.path.splitext(output)[1]
if not output_fmt:
output_fmt = '.oeb'
output_fmt = output_fmt[1:].lower()
self.input_plugin = plugin_for_input_format(input_fmt)
self.output_plugin = plugin_for_output_format(output_fmt)

View File

@ -5,20 +5,20 @@ __copyright__ = '2008 Kovid Goyal <kovid at kovidgoyal.net>'
Iterate over the HTML files in an ebook. Useful for writing viewers.
'''
import re, os, math, copy
import re, os, math
from cStringIO import StringIO
from PyQt4.Qt import QFontDatabase
from calibre.ebooks.epub.from_any import MAP
from calibre.customize.ui import available_input_formats
from calibre.ebooks.epub.from_html import TITLEPAGE
from calibre.ebooks.epub import config
from calibre.ebooks.metadata.opf2 import OPF
from calibre.ebooks.metadata.opf2 import OPF, OPFCreator
from calibre.ptempfile import TemporaryDirectory
from calibre.ebooks.chardet import xml_to_unicode
from calibre.ebooks.html_old import create_dir
from calibre.utils.zipfile import safe_replace, ZipFile
from calibre.utils.config import DynamicConfig
from calibre.utils.logging import Log
from calibre import CurrentDir
def character_count(html):
'''
@ -50,11 +50,28 @@ class SpineItem(unicode):
obj.max_page = -1
return obj
def html2opf(path, tdir, opts):
opts = copy.copy(opts)
opts.output = tdir
create_dir(path, opts)
return os.path.join(tdir, 'metadata.opf')
class FakeOpts(object):
verbose = 0
breadth_first = False
max_levels = 5
input_encoding = None
def html2opf(path, tdir, log):
from calibre.ebooks.html.input import get_filelist
from calibre.ebooks.metadata.meta import get_metadata
with CurrentDir(tdir):
fl = get_filelist(path, tdir, FakeOpts(), log)
mi = get_metadata(open(path, 'rb'), 'html')
mi = OPFCreator(os.getcwdu(), mi)
mi.guide = None
entries = [(f.path, 'application/xhtml+xml') for f in fl]
mi.create_manifest(entries)
mi.create_spine([f.path for f in fl])
mi.render(open('metadata.opf', 'wb'))
opfpath = os.path.abspath('metadata.opf')
return opfpath
def opf2opf(path, tdir, opts):
return path
@ -62,24 +79,22 @@ def opf2opf(path, tdir, opts):
def is_supported(path):
ext = os.path.splitext(path)[1].replace('.', '').lower()
ext = re.sub(r'(x{0,1})htm(l{0,1})', 'html', ext)
return ext in list(MAP.keys())+['html', 'opf']
return ext in available_input_formats()
class EbookIterator(object):
CHARACTERS_PER_PAGE = 1000
def __init__(self, pathtoebook):
def __init__(self, pathtoebook, log=None):
self.log = log
if log is None:
self.log = Log()
pathtoebook = pathtoebook.strip()
self.pathtoebook = os.path.abspath(pathtoebook)
self.config = DynamicConfig(name='iterator')
ext = os.path.splitext(pathtoebook)[1].replace('.', '').lower()
ext = re.sub(r'(x{0,1})htm(l{0,1})', 'html', ext)
map = dict(MAP)
map['html'] = html2opf
map['opf'] = opf2opf
if ext not in map.keys():
raise UnsupportedFormatError(ext)
self.to_opf = map[ext]
self.ebook_ext = ext
def search(self, text, index):
text = text.lower()
@ -115,14 +130,24 @@ class EbookIterator(object):
def __enter__(self):
self._tdir = TemporaryDirectory('_ebook_iter')
self.base = self._tdir.__enter__()
opts = config('').parse()
self.pathtoopf = self.to_opf(self.pathtoebook, self.base, opts)
if self.ebook_ext == 'opf':
self.pathtoopf = self.pathtoebook
elif self.ebook_ext == 'html':
self.pathtoopf = html2opf(self.pathtoebook, self.base, self.log)
else:
from calibre.ebooks.conversion.plumber import Plumber
plumber = Plumber(self.pathtoebook, self.base, self.log)
plumber.setup_options()
self.pathtoopf = plumber.input_plugin(open(plumber.input, 'rb'),
plumber.opts, plumber.input_fmt, self.log,
{}, self.base)
self.opf = OPF(self.pathtoopf, os.path.dirname(self.pathtoopf))
self.spine = [SpineItem(i.path) for i in self.opf.spine]
cover = self.opf.cover
if os.path.splitext(self.pathtoebook)[1].lower() in \
('.lit', '.mobi', '.prc') and cover:
if self.ebook_ext in ('lit', 'mobi', 'prc', 'opf') and cover:
cfile = os.path.join(os.path.dirname(self.spine[0]), 'calibre_ei_cover.html')
open(cfile, 'wb').write(TITLEPAGE%cover)
self.spine[0:0] = [SpineItem(cfile)]
@ -131,7 +156,6 @@ class EbookIterator(object):
self.opf.path_to_html_toc not in self.spine:
self.spine.append(SpineItem(self.opf.path_to_html_toc))
sizes = [i.character_count for i in self.spine]
self.pages = [math.ceil(i/float(self.CHARACTERS_PER_PAGE)) for i in sizes]
for p, s in zip(self.pages, self.spine):

View File

@ -17,14 +17,14 @@ from calibre.gui2.viewer.bookmarkmanager import BookmarkManager
from calibre.gui2.main_window import MainWindow
from calibre.gui2 import Application, ORG_NAME, APP_UID, choose_files, \
info_dialog, error_dialog
from calibre.ebooks.epub.iterator import EbookIterator
from calibre.ebooks.epub.from_any import SOURCE_FORMATS
from calibre.ebooks.oeb.iterator import EbookIterator
from calibre.ebooks import DRMError
from calibre.gui2.dialogs.conversion_error import ConversionErrorDialog
from calibre.constants import islinux
from calibre.utils.config import Config, StringConfig
from calibre.gui2.library import SearchBox
from calibre.ebooks.metadata import MetaInformation
from calibre.customize.ui import available_input_formats
class TOCItem(QStandardItem):
@ -362,7 +362,8 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
def open_ebook(self, checked):
files = choose_files(self, 'ebook viewer open dialog',
_('Choose ebook'),
[(_('Ebooks'), SOURCE_FORMATS)], all_files=False,
[(_('Ebooks'), available_input_formats())],
all_files=False,
select_only_single_file=True)
if files:
self.load_ebook(files[0])

View File

@ -445,6 +445,8 @@ class BasicNewsRecipe(object):
:param progress_reporter: A Callable that takes two arguments: progress (a number between 0 and 1) and a string message. The message should be optional.
'''
self.log = Log()
if options.verbose:
self.log.filter_level = self.log.DEBUG
if not isinstance(self.title, unicode):
self.title = unicode(self.title, 'utf-8', 'replace')