home *** CD-ROM | disk | FTP | other *** search
Wrap
# Source Generated with Decompyle++ # File: in.pyc (Python 2.6) from __future__ import with_statement __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>' import os import shutil import traceback import functools import sys import re from contextlib import closing from calibre.customize import Plugin, CatalogPlugin, FileTypePlugin, MetadataReaderPlugin, MetadataWriterPlugin from calibre.customize.conversion import InputFormatPlugin, OutputFormatPlugin from calibre.customize.profiles import InputProfile, OutputProfile from calibre.customize.builtins import plugins as builtin_plugins from calibre.constants import numeric_version as version, iswindows, isosx from calibre.devices.interface import DevicePlugin from calibre.ebooks.metadata import MetaInformation from calibre.ebooks.metadata.covers import CoverDownload from calibre.ebooks.metadata.fetch import MetadataSource from calibre.utils.config import make_config_dir, Config, ConfigProxy, plugin_dir, OptionParser, prefs from calibre.ebooks.epub.fix import ePubFixer platform = 'linux' if iswindows: platform = 'windows' elif isosx: platform = 'osx' from zipfile import ZipFile def _config(): c = Config('customize') c.add_opt('plugins', default = { }, help = _('Installed plugins')) 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')) c.add_opt('enabled_plugins', default = set([]), help = _('Enabled plugins')) return ConfigProxy(c) config = _config() class InvalidPlugin(ValueError): pass class PluginNotFound(ValueError): pass def find_plugin(name): for plugin in _initialized_plugins: if plugin.name == name: return plugin def load_plugin(path_to_zip_file): if not os.access(path_to_zip_file, os.R_OK): raise PluginNotFound os.access(path_to_zip_file, os.R_OK) try: zf = _[1] for name in zf.namelist(): if name.lower().endswith('plugin.py'): locals = { } raw = zf.read(name) match = re.search('coding[:=]\\s*([-\\w.]+)', raw[:300]) encoding = 'utf-8' raw = raw.decode(encoding) raw = re.sub('\r\n', '\n', raw) exec raw in locals for x in locals.values(): if isinstance(x, type) and issubclass(x, Plugin) and x.name != 'Trivial Plugin': if x.minimum_calibre_version > version or platform not in x.supported_platforms: continue return x x.name != 'Trivial Plugin' finally: pass raise InvalidPlugin(_('No valid plugin found in ') + path_to_zip_file) def disable_plugin(plugin_or_name): x = getattr(plugin_or_name, 'name', plugin_or_name) plugin = find_plugin(x) if not plugin.can_be_disabled: raise ValueError('Plugin %s cannot be disabled' % x) plugin.can_be_disabled dp = config['disabled_plugins'] dp.add(x) config['disabled_plugins'] = dp ep = config['enabled_plugins'] if x in ep: ep.remove(x) config['enabled_plugins'] = ep def enable_plugin(plugin_or_name): x = getattr(plugin_or_name, 'name', plugin_or_name) dp = config['disabled_plugins'] if x in dp: dp.remove(x) config['disabled_plugins'] = dp ep = config['enabled_plugins'] ep.add(x) config['enabled_plugins'] = ep default_disabled_plugins = set([ 'Douban Books']) def is_disabled(plugin): if plugin.name in config['enabled_plugins']: return False if not plugin.name in config['disabled_plugins']: pass return plugin.name in default_disabled_plugins _on_import = { } _on_preprocess = { } _on_postprocess = { } def reread_filetype_plugins(): global _on_import, _on_preprocess, _on_postprocess _on_import = { } _on_preprocess = { } _on_postprocess = { } for plugin in _initialized_plugins: if isinstance(plugin, FileTypePlugin): for ft in plugin.file_types: if plugin.on_import: if not _on_import.has_key(ft): _on_import[ft] = [] _on_import[ft].append(plugin) if plugin.on_preprocess: if not _on_preprocess.has_key(ft): _on_preprocess[ft] = [] _on_preprocess[ft].append(plugin) if plugin.on_postprocess: if not _on_postprocess.has_key(ft): _on_postprocess[ft] = [] _on_postprocess[ft].append(plugin) continue def _run_filetype_plugins(path_to_file, ft = None, occasion = 'preprocess'): occasion_plugins = { '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('.', '') nfp = path_to_file for plugin in occasion_plugins.get(ft, []): if is_disabled(plugin): continue plugin.site_customization = customization.get(plugin.name, '') plugin.__enter__() try: nfp = plugin.run(path_to_file) if not nfp: nfp = path_to_file except: plugin.__exit__ plugin print 'Running file type plugin %s failed with traceback:' % plugin.name traceback.print_exc() finally: pass x = lambda j: os.path.normpath(os.path.normcase(j)) return nfp run_plugins_on_import = functools.partial(_run_filetype_plugins, occasion = 'import') run_plugins_on_preprocess = functools.partial(_run_filetype_plugins, occasion = 'preprocess') run_plugins_on_postprocess = functools.partial(_run_filetype_plugins, occasion = 'postprocess') def customize_plugin(plugin, custom): d = config['plugin_customization'] d[plugin.name] = custom.strip() config['plugin_customization'] = d def plugin_customization(plugin): return config['plugin_customization'].get(plugin.name, '') def input_profiles(): for plugin in _initialized_plugins: if isinstance(plugin, InputProfile): yield plugin continue def output_profiles(): for plugin in _initialized_plugins: if isinstance(plugin, OutputProfile): yield plugin continue def metadata_sources(metadata_type = 'basic', customize = True, isbndb_key = None): for plugin in _initialized_plugins: if isinstance(plugin, MetadataSource) and plugin.metadata_type == metadata_type: if is_disabled(plugin): continue if customize: customization = config['plugin_customization'] plugin.site_customization = customization.get(plugin.name, None) if plugin.name == 'IsbnDB' and isbndb_key is not None: plugin.site_customization = isbndb_key yield plugin continue def get_isbndb_key(): return config['plugin_customization'].get('IsbnDB', None) def set_isbndb_key(key): for plugin in _initialized_plugins: if plugin.name == 'IsbnDB': return customize_plugin(plugin, key) def migrate_isbndb_key(): key = prefs['isbndb_com_key'] if key: prefs.set('isbndb_com_key', '') set_isbndb_key(key) def cover_sources(): customization = config['plugin_customization'] for plugin in _initialized_plugins: if isinstance(plugin, CoverDownload): if not is_disabled(plugin): plugin.site_customization = customization.get(plugin.name, '') yield plugin is_disabled(plugin) _metadata_readers = { } _metadata_writers = { } def reread_metadata_plugins(): global _metadata_readers _metadata_readers = { } for plugin in _initialized_plugins: if isinstance(plugin, MetadataReaderPlugin): for ft in plugin.file_types: if not _metadata_readers.has_key(ft): _metadata_readers[ft] = [] _metadata_readers[ft].append(plugin) if isinstance(plugin, MetadataWriterPlugin): for ft in plugin.file_types: if not _metadata_writers.has_key(ft): _metadata_writers[ft] = [] _metadata_writers[ft].append(plugin) def metadata_readers(): ans = set([]) for plugins in _metadata_readers.values(): for plugin in plugins: ans.add(plugin) return ans def metadata_writers(): ans = set([]) for plugins in _metadata_writers.values(): for plugin in plugins: ans.add(plugin) return ans class QuickMetadata(object): def __init__(self): self.quick = False def __enter__(self): self.quick = True def __exit__(self, *args): self.quick = False quick_metadata = QuickMetadata() class ApplyNullMetadata(object): def __init__(self): self.apply_null = False def __enter__(self): self.apply_null = True def __exit__(self, *args): self.apply_null = False apply_null_metadata = ApplyNullMetadata() def get_file_type_metadata(stream, ftype): mi = MetaInformation(None, None) ftype = ftype.lower().strip() if _metadata_readers.has_key(ftype): for plugin in _metadata_readers[ftype]: if not is_disabled(plugin): plugin.__enter__() try: plugin.quick = quick_metadata.quick mi = plugin.get_metadata(stream, ftype.lower().strip()) except: plugin.__exit__ plugin traceback.print_exc() continue finally: pass continue plugin.__exit__ return mi def set_file_type_metadata(stream, mi, ftype): ftype = ftype.lower().strip() if _metadata_writers.has_key(ftype): for plugin in _metadata_writers[ftype]: if not is_disabled(plugin): plugin.__enter__() try: plugin.apply_null = apply_null_metadata.apply_null plugin.set_metadata(stream, mi, ftype.lower().strip()) except: plugin.__exit__ plugin print 'Failed to set metadata for', repr(getattr(mi, 'title', '')) traceback.print_exc() finally: pass continue plugin.__exit__ def add_plugin(path_to_zip_file): make_config_dir() plugin = load_plugin(path_to_zip_file) plugin = initialize_plugin(plugin, path_to_zip_file) plugins = config['plugins'] zfp = os.path.join(plugin_dir, plugin.name + '.zip') if os.path.exists(zfp): os.remove(zfp) shutil.copyfile(path_to_zip_file, zfp) plugins[plugin.name] = zfp config['plugins'] = plugins initialize_plugins() return plugin def remove_plugin(plugin_or_name): name = getattr(plugin_or_name, 'name', plugin_or_name) plugins = config['plugins'] removed = False if name in plugins.keys(): removed = True zfp = plugins[name] if os.path.exists(zfp): os.remove(zfp) plugins.pop(name) config['plugins'] = plugins initialize_plugins() return removed def input_format_plugins(): for plugin in _initialized_plugins: if isinstance(plugin, InputFormatPlugin): yield plugin continue def plugin_for_input_format(fmt): customization = config['plugin_customization'] for plugin in input_format_plugins(): if fmt.lower() in plugin.file_types: plugin.site_customization = customization.get(plugin.name, None) return plugin def all_input_formats(): formats = set([]) for plugin in input_format_plugins(): for format in plugin.file_types: formats.add(format) return formats def available_input_formats(): formats = set([]) for plugin in input_format_plugins(): if not is_disabled(plugin): for format in plugin.file_types: formats.add(format) (formats.add('zip'), formats.add('rar')) return formats def output_format_plugins(): for plugin in _initialized_plugins: if isinstance(plugin, OutputFormatPlugin): yield plugin continue def plugin_for_output_format(fmt): customization = config['plugin_customization'] for plugin in output_format_plugins(): if fmt.lower() == plugin.file_type: plugin.site_customization = customization.get(plugin.name, None) return plugin def available_output_formats(): formats = set([]) for plugin in output_format_plugins(): if not is_disabled(plugin): formats.add(plugin.file_type) continue return formats def catalog_plugins(): for plugin in _initialized_plugins: if isinstance(plugin, CatalogPlugin): yield plugin continue def available_catalog_formats(): formats = set([]) for plugin in catalog_plugins(): if not is_disabled(plugin): for format in plugin.file_types: formats.add(format) return formats def plugin_for_catalog_format(fmt): for plugin in catalog_plugins(): if fmt.lower() in plugin.file_types: return plugin def device_plugins(): for plugin in _initialized_plugins: if isinstance(plugin, DevicePlugin): if not is_disabled(plugin): if platform in plugin.supported_platforms: yield plugin is_disabled(plugin) def epub_fixers(): for plugin in _initialized_plugins: if isinstance(plugin, ePubFixer): if not is_disabled(plugin): if platform in plugin.supported_platforms: yield plugin is_disabled(plugin) _initialized_plugins = [] def initialize_plugin(plugin, path_to_zip_file): try: p = plugin(path_to_zip_file) p.initialize() return p except Exception: print 'Failed to initialize plugin:', plugin.name, plugin.version tb = traceback.format_exc() raise InvalidPlugin(_('Initialization of plugin %s failed with traceback:') % tb + '\n' + tb) def initialize_plugins(): global _initialized_plugins _initialized_plugins = [] for zfp in list(config['plugins'].values()) + builtin_plugins: try: try: plugin = None if not isinstance(zfp, type) else zfp except PluginNotFound: continue plugin = None(initialize_plugin, plugin if isinstance(zfp, type) else zfp) _initialized_plugins.append(plugin) continue print 'Failed to initialize plugin...' traceback.print_exc() continue _initialized_plugins.sort(cmp = (lambda x, y: cmp(x.priority, y.priority)), reverse = True) reread_filetype_plugins() reread_metadata_plugins() initialize_plugins() def initialized_plugins(): for plugin in _initialized_plugins: yield plugin def option_parser(): parser = OptionParser(usage = _(' %prog options\n\n Customize calibre by loading external plugins.\n ')) 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, 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.')) parser.add_option('-l', '--list-plugins', default = False, action = 'store_true', help = _('List all installed plugins')) parser.add_option('--enable-plugin', default = None, help = _('Enable the named plugin')) parser.add_option('--disable-plugin', default = None, help = _('Disable the named plugin')) return parser def main(args = sys.argv): parser = option_parser() if len(args) < 2: parser.print_help() return 1 (opts, args) = parser.parse_args(args) if opts.enable_plugin is not None: enable_plugin(opts.enable_plugin.strip()) if opts.disable_plugin is not None: disable_plugin(opts.disable_plugin.strip()) if opts.list_plugins: fmt = '%-15s%-20s%-15s%-15s%s' print fmt % tuple('Type|Name|Version|Disabled|Site Customization'.split('|')) print for plugin in initialized_plugins(): print fmt % (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())