Skip to content

Commit

Permalink
Add a callback to FileTypePlugins that is useful for modifying the bo…
Browse files Browse the repository at this point in the history
…ok record in the database when it is first created
  • Loading branch information
kovidgoyal committed Jan 4, 2016
1 parent 8fce6f0 commit c956a64
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 29 deletions.
18 changes: 16 additions & 2 deletions src/calibre/customize/__init__.py
Expand Up @@ -179,8 +179,7 @@ def size_dialog():
help_text = self.customization_help(gui=True)
help_text = QLabel(help_text, config_dialog)
help_text.setWordWrap(True)
help_text.setTextInteractionFlags(Qt.LinksAccessibleByMouse
| Qt.LinksAccessibleByKeyboard)
help_text.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard)
help_text.setOpenExternalLinks(True)
v.addWidget(help_text)
sc = plugin_customization(self)
Expand Down Expand Up @@ -369,6 +368,21 @@ def postimport(self, book_id, book_format, db):
'''
pass # Default implementation does nothing

def postadd(self, book_id, fmt_map, db):
'''
Called post add, i.e. after a book has been added to the db. Note that
this is different from :meth:`postimport`, which is called after a single book file
has been added to a book. postadd() is called only when an entire book record
with possibly more than one book file has been created for the first time.
This is useful if you wish to modify the book record in the database when the
book is first added to calibre.
:param book_id: Database id of the added book.
:param fmt_map: Map of file format to path from which the file format was added
:param db: Library database
'''
pass # Default implementation does nothing

# }}}

class MetadataReaderPlugin(Plugin): # {{{
Expand Down
51 changes: 29 additions & 22 deletions src/calibre/customize/ui.py
Expand Up @@ -3,6 +3,7 @@
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'

import os, shutil, traceback, functools, sys
from collections import defaultdict

from calibre.customize import (CatalogPlugin, FileTypePlugin, PluginNotFound,
MetadataReaderPlugin, MetadataWriterPlugin,
Expand Down Expand Up @@ -44,7 +45,7 @@ def find_plugin(name):
return plugin


def load_plugin(path_to_zip_file): # {{{
def load_plugin(path_to_zip_file): # {{{
'''
Load plugin from zip file or raise InvalidPlugin error
Expand Down Expand Up @@ -95,7 +96,8 @@ def restore_plugin_state_to_default(plugin_or_name):
])

def is_disabled(plugin):
if plugin.name in config['enabled_plugins']: return False
if plugin.name in config['enabled_plugins']:
return False
return plugin.name in config['disabled_plugins'] or \
plugin.name in default_disabled_plugins
# }}}
Expand All @@ -106,35 +108,30 @@ def is_disabled(plugin):
_on_postimport = {}
_on_preprocess = {}
_on_postprocess = {}
_on_postadd = []

def reread_filetype_plugins():
global _on_import
global _on_postimport
global _on_preprocess
global _on_postprocess
_on_import = {}
_on_postimport = {}
_on_preprocess = {}
_on_postprocess = {}
_on_import = defaultdict(list)
_on_postimport = defaultdict(list)
_on_preprocess = defaultdict(list)
_on_postprocess = defaultdict(list)
_on_postadd = []

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_postimport:
if not _on_postimport.has_key(ft):
_on_postimport[ft] = []
_on_postimport[ft].append(plugin)
_on_postadd.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)


Expand Down Expand Up @@ -187,6 +184,20 @@ def run_plugins_on_postimport(db, book_id, fmt):
plugin.name)
traceback.print_exc()

def run_plugins_on_postadd(db, book_id, fmt_map):
customization = config['plugin_customization']
for plugin in _on_postadd:
if is_disabled(plugin):
continue
plugin.site_customization = customization.get(plugin.name, '')
with plugin:
try:
plugin.postadd(book_id, fmt_map, db)
except Exception:
print ('Running file type plugin %s failed with traceback:'%
plugin.name)
traceback.print_exc()

# }}}

# Plugin customization {{{
Expand Down Expand Up @@ -268,17 +279,14 @@ def available_stores():
def reread_metadata_plugins():
global _metadata_readers
global _metadata_writers
_metadata_readers = {}
_metadata_readers = defaultdict(list)
_metadata_writers = defaultdict(list)
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)
elif 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():
Expand Down Expand Up @@ -338,7 +346,7 @@ def get_file_type_metadata(stream, ftype):
mi = MetaInformation(None, None)

ftype = ftype.lower().strip()
if _metadata_readers.has_key(ftype):
if ftype in _metadata_readers:
for plugin in _metadata_readers[ftype]:
if not is_disabled(plugin):
with plugin:
Expand All @@ -355,7 +363,7 @@ def get_file_type_metadata(stream, ftype):

def set_file_type_metadata(stream, mi, ftype, report_error=None):
ftype = ftype.lower().strip()
if _metadata_writers.has_key(ftype):
if ftype in _metadata_writers:
for plugin in _metadata_writers[ftype]:
if not is_disabled(plugin):
with plugin:
Expand Down Expand Up @@ -708,4 +716,3 @@ def main(args=sys.argv):
if __name__ == '__main__':
sys.exit(main())
# }}}

7 changes: 5 additions & 2 deletions src/calibre/db/cache.py
Expand Up @@ -15,7 +15,7 @@

from calibre import isbytestring, as_unicode
from calibre.constants import iswindows, preferred_encoding
from calibre.customize.ui import run_plugins_on_import, run_plugins_on_postimport
from calibre.customize.ui import run_plugins_on_import, run_plugins_on_postimport, run_plugins_on_postadd
from calibre.db import SPOOL_SIZE, _get_next_series_num_for_list
from calibre.db.categories import get_categories
from calibre.db.locking import create_locks, DowngradeLockError, SafeReadLock
Expand Down Expand Up @@ -1544,14 +1544,17 @@ def add_books(self, books, add_duplicates=True, apply_import_tags=True, preserve
as per the simple duplicate detection heuristic used by :meth:`has_book`.
'''
duplicates, ids = [], []
fmt_map = {}
for mi, format_map in books:
book_id = self.create_book_entry(mi, add_duplicates=add_duplicates, apply_import_tags=apply_import_tags, preserve_uuid=preserve_uuid)
if book_id is None:
duplicates.append((mi, format_map))
else:
ids.append(book_id)
for fmt, stream_or_path in format_map.iteritems():
self.add_format(book_id, fmt, stream_or_path, dbapi=dbapi, run_hooks=run_hooks)
if self.add_format(book_id, fmt, stream_or_path, dbapi=dbapi, run_hooks=run_hooks):
fmt_map[fmt.lower()] = getattr(stream_or_path, 'name', stream_or_path) or '<stream>'
run_plugins_on_postadd(dbapi or self, book_id, fmt_map)
return ids, duplicates

@write_api
Expand Down
10 changes: 7 additions & 3 deletions src/calibre/gui2/add.py
Expand Up @@ -16,7 +16,7 @@

from calibre import prints, as_unicode
from calibre.constants import DEBUG
from calibre.customize.ui import run_plugins_on_postimport
from calibre.customize.ui import run_plugins_on_postimport, run_plugins_on_postadd
from calibre.db.adding import find_books_in_directory
from calibre.db.utils import find_identical_books
from calibre.ebooks.metadata.book.base import Metadata
Expand Down Expand Up @@ -375,7 +375,7 @@ def add_book(self, mi, cover_path, paths):
[a('\t' + f) for f in paths]
a(_('With error:')), a(traceback.format_exc())
return
self.add_formats(book_id, paths, mi)
self.add_formats(book_id, paths, mi, is_an_add=True)
try:
if self.add_formats_to_existing:
self.db.update_data_for_find_identical_books(book_id, self.find_identical_books_data)
Expand All @@ -388,8 +388,9 @@ def add_book(self, mi, cover_path, paths):
if DEBUG:
prints('Added', mi.title, 'to db in: %.1f' % (time.time() - st))

def add_formats(self, book_id, paths, mi, replace=True):
def add_formats(self, book_id, paths, mi, replace=True, is_an_add=False):
fmap = {p.rpartition(os.path.extsep)[-1].lower():p for p in paths}
fmt_map = {}
for fmt, path in fmap.iteritems():
# The onimport plugins have already been run by the read metadata
# worker
Expand All @@ -398,11 +399,14 @@ def add_formats(self, book_id, paths, mi, replace=True):
try:
if self.db.add_format(book_id, fmt, path, run_hooks=False, replace=replace):
run_plugins_on_postimport(self.dbref(), book_id, fmt)
fmt_map[fmt.lower()] = path
except Exception:
a = self.report.append
a(''), a('-' * 70)
a(_('Failed to add the file {0} to the book: {1}').format(path, mi.title))
a(_('With error:')), a(traceback.format_exc())
if is_an_add:
run_plugins_on_postadd(self.dbref(), book_id, fmt_map)

def process_duplicates(self):
if self.duplicates:
Expand Down

0 comments on commit c956a64

Please sign in to comment.