mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 10:14:46 -04:00
GR Catalog Plugin implementation
This commit is contained in:
parent
2673542326
commit
00b4b1194a
@ -48,7 +48,7 @@ class Plugin(object):
|
|||||||
#: the plugins are run in order of decreasing priority
|
#: the plugins are run in order of decreasing priority
|
||||||
#: i.e. plugins with higher priority will be run first.
|
#: i.e. plugins with higher priority will be run first.
|
||||||
#: The highest possible priority is ``sys.maxint``.
|
#: The highest possible priority is ``sys.maxint``.
|
||||||
#: Default pririty is 1.
|
#: Default priority is 1.
|
||||||
priority = 1
|
priority = 1
|
||||||
|
|
||||||
#: The earliest version of calibre this plugin requires
|
#: The earliest version of calibre this plugin requires
|
||||||
@ -226,4 +226,55 @@ class MetadataWriterPlugin(Plugin):
|
|||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class CatalogPlugin(Plugin):
|
||||||
|
'''
|
||||||
|
A plugin that implements a catalog generator.
|
||||||
|
'''
|
||||||
|
|
||||||
|
#: Output file type for which this plugin should be run
|
||||||
|
#: For example: 'epub' or 'xml'
|
||||||
|
file_types = set([])
|
||||||
|
|
||||||
|
type = _('Catalog generator')
|
||||||
|
|
||||||
|
#: CLI parser options specific to this plugin, declared as namedtuple Option
|
||||||
|
#:
|
||||||
|
#: from collections import namedtuple
|
||||||
|
#: Option = namedtuple('Option', 'option, default, dest, help')
|
||||||
|
#: cli_options = [Option('--catalog-title',
|
||||||
|
#: default = 'My Catalog',
|
||||||
|
#: dest = 'catalog_title',
|
||||||
|
#: help = (_('Title of generated catalog. \nDefault:') + " '" +
|
||||||
|
#: '%default' + "'"))]
|
||||||
|
|
||||||
|
cli_options = []
|
||||||
|
|
||||||
|
def run(self, path_to_output, opts, log):
|
||||||
|
'''
|
||||||
|
Run the plugin. Must be implemented in subclasses.
|
||||||
|
It should generate the catalog in the format specified
|
||||||
|
in file_types, returning the absolute path to the
|
||||||
|
generated catalog file. If an error is encountered
|
||||||
|
it should raise an Exception and return None. The default
|
||||||
|
implementation simply returns None.
|
||||||
|
|
||||||
|
The generated catalog file should be created with the
|
||||||
|
:meth:`temporary_file` method.
|
||||||
|
|
||||||
|
:param path_to_output: Absolute path to the generated catalog file.
|
||||||
|
:param opts: A dictionary of keyword arguments
|
||||||
|
|
||||||
|
:return: Absolute path to the modified ebook.
|
||||||
|
|
||||||
|
Access the opts object as a dictionary with this code:
|
||||||
|
opts_dict = vars(opts)
|
||||||
|
keys = opts_dict.keys()
|
||||||
|
keys.sort()
|
||||||
|
print "opts:"
|
||||||
|
for key in keys:
|
||||||
|
print "\t%s: %s" % (key, opts_dict[key])
|
||||||
|
|
||||||
|
'''
|
||||||
|
# Default implementation does nothing
|
||||||
|
print "CatalogPlugin.generate_catalog() default method, should be overridden in subclass"
|
||||||
|
return None
|
||||||
|
@ -5,8 +5,8 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
import os, shutil, traceback, functools, sys, re
|
import os, shutil, traceback, functools, sys, re
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
|
||||||
from calibre.customize import Plugin, FileTypePlugin, MetadataReaderPlugin, \
|
from calibre.customize import Plugin, CatalogPlugin, FileTypePlugin, \
|
||||||
MetadataWriterPlugin
|
MetadataReaderPlugin, MetadataWriterPlugin
|
||||||
from calibre.customize.conversion import InputFormatPlugin, OutputFormatPlugin
|
from calibre.customize.conversion import InputFormatPlugin, OutputFormatPlugin
|
||||||
from calibre.customize.profiles import InputProfile, OutputProfile
|
from calibre.customize.profiles import InputProfile, OutputProfile
|
||||||
from calibre.customize.builtins import plugins as builtin_plugins
|
from calibre.customize.builtins import plugins as builtin_plugins
|
||||||
@ -300,6 +300,7 @@ def find_plugin(name):
|
|||||||
if plugin.name == name:
|
if plugin.name == name:
|
||||||
return plugin
|
return plugin
|
||||||
|
|
||||||
|
|
||||||
def input_format_plugins():
|
def input_format_plugins():
|
||||||
for plugin in _initialized_plugins:
|
for plugin in _initialized_plugins:
|
||||||
if isinstance(plugin, InputFormatPlugin):
|
if isinstance(plugin, InputFormatPlugin):
|
||||||
@ -328,6 +329,7 @@ def available_input_formats():
|
|||||||
formats.add('zip'), formats.add('rar')
|
formats.add('zip'), formats.add('rar')
|
||||||
return formats
|
return formats
|
||||||
|
|
||||||
|
|
||||||
def output_format_plugins():
|
def output_format_plugins():
|
||||||
for plugin in _initialized_plugins:
|
for plugin in _initialized_plugins:
|
||||||
if isinstance(plugin, OutputFormatPlugin):
|
if isinstance(plugin, OutputFormatPlugin):
|
||||||
@ -347,6 +349,27 @@ def available_output_formats():
|
|||||||
formats.add(plugin.file_type)
|
formats.add(plugin.file_type)
|
||||||
return formats
|
return formats
|
||||||
|
|
||||||
|
|
||||||
|
def catalog_plugins():
|
||||||
|
for plugin in _initialized_plugins:
|
||||||
|
if isinstance(plugin, CatalogPlugin):
|
||||||
|
yield plugin
|
||||||
|
|
||||||
|
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
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
def device_plugins():
|
def device_plugins():
|
||||||
for plugin in _initialized_plugins:
|
for plugin in _initialized_plugins:
|
||||||
if isinstance(plugin, DevicePlugin):
|
if isinstance(plugin, DevicePlugin):
|
||||||
|
@ -583,8 +583,121 @@ def command_export(args, dbpath):
|
|||||||
do_export(get_db(dbpath, opts), ids, dir, opts)
|
do_export(get_db(dbpath, opts), ids, dir, opts)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
# GR additions
|
||||||
|
|
||||||
|
def catalog_option_parser(args):
|
||||||
|
from calibre.customize.ui import available_catalog_formats, plugin_for_catalog_format
|
||||||
|
from calibre.utils.logging import Log
|
||||||
|
|
||||||
|
def add_plugin_parser_options(fmt, parser, log):
|
||||||
|
|
||||||
|
# Fetch the extension-specific CLI options from the plugin
|
||||||
|
plugin = plugin_for_catalog_format(fmt)
|
||||||
|
for option in plugin.cli_options:
|
||||||
|
parser.add_option(option.option,
|
||||||
|
default=option.default,
|
||||||
|
dest=option.dest,
|
||||||
|
help=option.help)
|
||||||
|
|
||||||
|
# print_help(parser, log)
|
||||||
|
return plugin
|
||||||
|
|
||||||
|
def print_help(parser, log):
|
||||||
|
help = parser.format_help().encode(preferred_encoding, 'replace')
|
||||||
|
log(help)
|
||||||
|
|
||||||
|
def validate_command_line(parser, args, log):
|
||||||
|
# calibredb catalog path/to/destination.[epub|csv|xml|...] [options]
|
||||||
|
|
||||||
|
# Validate form
|
||||||
|
if not len(args) or args[0].startswith('-'):
|
||||||
|
print_help(parser, log)
|
||||||
|
log.error("\n\nYou must specify a catalog output file of the form 'path/to/destination.extension'\n"
|
||||||
|
"To review options for an output format, type 'calibredb catalog <.extension> --help'\n"
|
||||||
|
"For example, 'calibredb catalog .xml --help'\n")
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
# Validate plugin exists for specified output format
|
||||||
|
output = os.path.abspath(args[0])
|
||||||
|
file_extension = output[output.rfind('.') + 1:]
|
||||||
|
|
||||||
|
if not file_extension in available_catalog_formats():
|
||||||
|
print_help(parser, log)
|
||||||
|
log.error("No catalog plugin available for extension '%s'.\n" % file_extension +
|
||||||
|
"Catalog plugins available for %s\n" % ', '.join(available_catalog_formats()) )
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
return output, file_extension
|
||||||
|
|
||||||
|
# Entry point
|
||||||
|
log = Log()
|
||||||
|
parser = get_parser(_(
|
||||||
|
'''
|
||||||
|
%prog catalog /path/to/destination.(epub|csv|xml|...) [options]
|
||||||
|
|
||||||
|
Export a catalog in format specified by path/to/destination extension.
|
||||||
|
Options control how entries are displayed in the generated catalog ouput.
|
||||||
|
'''))
|
||||||
|
|
||||||
|
# Confirm that a plugin handler exists for specified output file extension
|
||||||
|
# Will raise SystemExit(1) if no plugin matching file_extension
|
||||||
|
output, fmt = validate_command_line(parser, args, log)
|
||||||
|
|
||||||
|
# Add options common to all catalog plugins
|
||||||
|
parser.add_option('-s', '--search', default=None, dest='search_text',
|
||||||
|
help=_("Filter the results by the search query. For the format of the search query, please see the search-related documentation in the User Manual.\n"+
|
||||||
|
"Default: no filtering"))
|
||||||
|
parser.add_option('-v','--verbose', default=False, action='store_true',
|
||||||
|
dest='verbose',
|
||||||
|
help=_('Show detailed output information. Useful for debugging'))
|
||||||
|
|
||||||
|
# Add options specific to fmt plugin
|
||||||
|
plugin = add_plugin_parser_options(fmt, parser, log)
|
||||||
|
|
||||||
|
# Merge options from GUI Preferences
|
||||||
|
'''
|
||||||
|
from calibre.library.save_to_disk import config
|
||||||
|
c = config()
|
||||||
|
for pref in ['asciiize', 'update_metadata', 'write_opf', 'save_cover']:
|
||||||
|
opt = c.get_option(pref)
|
||||||
|
switch = '--dont-'+pref.replace('_', '-')
|
||||||
|
parser.add_option(switch, default=True, action='store_false',
|
||||||
|
help=opt.help+' '+_('Specifying this switch will turn '
|
||||||
|
'this behavior off.'), dest=pref)
|
||||||
|
|
||||||
|
for pref in ['timefmt', 'template', 'formats']:
|
||||||
|
opt = c.get_option(pref)
|
||||||
|
switch = '--'+pref
|
||||||
|
parser.add_option(switch, default=opt.default,
|
||||||
|
help=opt.help, dest=pref)
|
||||||
|
|
||||||
|
for pref in ('replace_whitespace', 'to_lowercase'):
|
||||||
|
opt = c.get_option(pref)
|
||||||
|
switch = '--'+pref.replace('_', '-')
|
||||||
|
parser.add_option(switch, default=False, action='store_true',
|
||||||
|
help=opt.help)
|
||||||
|
'''
|
||||||
|
|
||||||
|
return parser, plugin, log
|
||||||
|
|
||||||
|
def command_catalog(args, dbpath):
|
||||||
|
parser, plugin, log = catalog_option_parser(args)
|
||||||
|
opts, args = parser.parse_args(sys.argv[1:])
|
||||||
|
if len(args) < 2:
|
||||||
|
parser.print_help()
|
||||||
|
print
|
||||||
|
print >>sys.stderr, _('Error: You must specify a catalog output file')
|
||||||
|
return 1
|
||||||
|
if opts.verbose:
|
||||||
|
log("library.cli:command_catalog dispatching to plugin %s" % plugin.name)
|
||||||
|
plugin.run(args[1], opts)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# end of GR additions
|
||||||
|
|
||||||
COMMANDS = ('list', 'add', 'remove', 'add_format', 'remove_format',
|
COMMANDS = ('list', 'add', 'remove', 'add_format', 'remove_format',
|
||||||
'show_metadata', 'set_metadata', 'export')
|
'show_metadata', 'set_metadata', 'export', 'catalog')
|
||||||
|
|
||||||
|
|
||||||
def option_parser():
|
def option_parser():
|
||||||
|
Loading…
x
Reference in New Issue
Block a user