Refactor the code to embed metadata into format files to enable re-use

This commit is contained in:
Kovid Goyal 2014-06-20 19:19:05 +05:30
parent 5036b68d8a
commit 542658a85f
3 changed files with 52 additions and 12 deletions

View File

@ -1214,6 +1214,13 @@ class DB(object):
shutil.copyfile(candidates[0], fmt_path) shutil.copyfile(candidates[0], fmt_path)
return fmt_path return fmt_path
def apply_to_format(self, book_id, path, fname, fmt, func, missing_value=None):
path = self.format_abspath(book_id, fmt, fname, path)
if path is None:
return missing_value
with lopen(path, 'r+b') as f:
return func(f)
def format_hash(self, book_id, fmt, fname, path): def format_hash(self, book_id, fmt, fname, path):
path = self.format_abspath(book_id, fmt, fname, path) path = self.format_abspath(book_id, fmt, fname, path)
if path is None: if path is None:

View File

@ -10,7 +10,7 @@ __docformat__ = 'restructuredtext en'
import os, traceback, random, shutil, re, operator import os, traceback, random, shutil, re, operator
from io import BytesIO from io import BytesIO
from collections import defaultdict from collections import defaultdict
from functools import wraps from functools import wraps, partial
from future_builtins import zip from future_builtins import zip
from calibre import isbytestring from calibre import isbytestring
@ -1685,8 +1685,7 @@ class Cache(object):
identical_book_ids = set() identical_book_ids = set()
if mi.authors: if mi.authors:
try: try:
quathors = mi.authors[:20] # Too many authors causes parsing of quathors = mi.authors[:20] # Too many authors causes parsing of the search expression to fail
# the search expression to fail
query = ' and '.join('authors:"=%s"'%(a.replace('"', '')) for a in quathors) query = ' and '.join('authors:"=%s"'%(a.replace('"', '')) for a in quathors)
qauthors = mi.authors[20:] qauthors = mi.authors[20:]
except ValueError: except ValueError:
@ -1797,5 +1796,44 @@ class Cache(object):
ans[book].append(lib) ans[book].append(lib)
return {k:tuple(sorted(v, key=sort_key)) for k, v in ans.iteritems()} return {k:tuple(sorted(v, key=sort_key)) for k, v in ans.iteritems()}
@write_api
def embed_metadata(self, book_ids, only_fmts=None):
''' Update metadata in all formats of the specified book_ids to current metadata in the database. '''
field = self.fields['formats']
from calibre.ebooks.metadata.opf2 import pretty_print
from calibre.customize.ui import apply_null_metadata
from calibre.ebooks.metadata.meta import set_metadata
if only_fmts:
only_fmts = {f.lower() for f in only_fmts}
def doit(fmt, mi, stream):
with apply_null_metadata, pretty_print:
set_metadata(stream, mi, stream_type=fmt)
stream.seek(0, os.SEEK_END)
return stream.tell()
for book_id in book_ids:
fmts = field.table.book_col_map.get(book_id, ())
if not fmts:
continue
mi = self.get_metadata(book_id, get_cover=True, cover_as_data=True)
try:
path = self._field_for('path', book_id).replace('/', os.sep)
except:
continue
for fmt in fmts:
if only_fmts is not None and fmt.lower() not in only_fmts:
continue
try:
name = self.fields['formats'].format_fname(book_id, fmt)
except:
continue
if name and path:
new_size = self.backend.apply_to_format(book_id, path, name, fmt, partial(doit, fmt, mi))
if new_size is not None:
self.format_metadata_cache[book_id].get(fmt, {})['size'] = new_size
max_size = self.fields['formats'].table.update_fmt(book_id, fmt, name, new_size, self.backend)
self.fields['size'].table.update_sizes({book_id: max_size})
# }}} # }}}

View File

@ -131,16 +131,11 @@ class TweakEpubAction(InterfaceAction):
'The %s format is missing from the calibre library. You should run' 'The %s format is missing from the calibre library. You should run'
' library maintenance.') % fmt, show=True) ' library maintenance.') % fmt, show=True)
tweak = 'ebook-edit' tweak = 'ebook-edit'
self.gui.setCursor(Qt.BusyCursor)
if tprefs['update_metadata_from_calibre']:
from calibre.ebooks.metadata.opf2 import pretty_print
from calibre.ebooks.metadata.meta import set_metadata
from calibre.customize.ui import apply_null_metadata
mi = db.new_api.get_metadata(book_id, get_cover=True)
with pretty_print, apply_null_metadata, open(path, 'r+b') as f:
set_metadata(f, mi, stream_type=fmt.lower())
notify = '%d:%s:%s:%s' % (book_id, fmt, db.library_id, db.library_path)
try: try:
self.gui.setCursor(Qt.BusyCursor)
if tprefs['update_metadata_from_calibre']:
db.new_api.embed_metadata((book_id,), only_fmts={fmt})
notify = '%d:%s:%s:%s' % (book_id, fmt, db.library_id, db.library_path)
self.gui.job_manager.launch_gui_app(tweak, kwargs=dict(path=path, notify=notify)) self.gui.job_manager.launch_gui_app(tweak, kwargs=dict(path=path, notify=notify))
time.sleep(2) time.sleep(2)
finally: finally: