mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Refactor the code to embed metadata into format files to enable re-use
This commit is contained in:
parent
5036b68d8a
commit
542658a85f
@ -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:
|
||||||
|
@ -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})
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
@ -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'
|
||||||
|
try:
|
||||||
self.gui.setCursor(Qt.BusyCursor)
|
self.gui.setCursor(Qt.BusyCursor)
|
||||||
if tprefs['update_metadata_from_calibre']:
|
if tprefs['update_metadata_from_calibre']:
|
||||||
from calibre.ebooks.metadata.opf2 import pretty_print
|
db.new_api.embed_metadata((book_id,), only_fmts={fmt})
|
||||||
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)
|
notify = '%d:%s:%s:%s' % (book_id, fmt, db.library_id, db.library_path)
|
||||||
try:
|
|
||||||
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:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user