mirror of
				https://github.com/kovidgoyal/calibre.git
				synced 2025-10-31 18:47:02 -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