Port calibredb export

This commit is contained in:
Kovid Goyal 2017-05-01 21:11:39 +05:30
parent dc86b78001
commit 4b09406136
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 133 additions and 14 deletions

View File

@ -4,19 +4,140 @@
from __future__ import absolute_import, division, print_function, unicode_literals from __future__ import absolute_import, division, print_function, unicode_literals
readonly = False import os
from calibre.db.cli import integers_from_string
from calibre.db.errors import NoSuchFormat
from calibre.library.save_to_disk import (
config, do_save_book_to_disk, get_formats, sanitize_args
)
from calibre.utils.formatter_functions import load_user_template_functions
readonly = True
version = 0 # change this if you change signature of implementation() version = 0 # change this if you change signature of implementation()
def implementation(db, notify_changes, *args): def implementation(db, notify_changes, action, *args):
is_remote = notify_changes is not None is_remote = notify_changes is not None
is_remote if action == 'all_ids':
return db.all_book_ids()
if action == 'setup':
book_id, formats = args
mi = db.get_metadata(book_id)
plugboards = db.pref('plugboards', {})
formats = get_formats(db.formats(book_id), formats)
return mi, plugboards, formats, db.library_id, db.pref(
'user_template_functions', []
)
if action == 'cover':
return db.cover(args[0])
if action == 'fmt':
book_id, fmt, dest = args
if is_remote:
return db.format(book_id, fmt)
db.copy_format_to(book_id, fmt, dest)
def option_parser(get_parser): def option_parser(get_parser):
pass parser = get_parser(
_(
'''\
%prog export [options] ids
Export the books specified by ids (a comma separated list) to the filesystem.
The export operation saves all formats of the book, its cover and metadata (in
an opf file). You can get id numbers from the search command.
'''
)
)
parser.add_option(
'--all',
default=False,
action='store_true',
help=_('Export all books in database, ignoring the list of ids.')
)
parser.add_option(
'--to-dir',
default='.',
help=(
_('Export books to the specified directory. Default is') + ' %default'
)
)
parser.add_option(
'--single-dir',
default=False,
action='store_true',
help=_('Export all books into a single directory')
)
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
class DBProxy(object):
# Proxy to allow do_save_book_to_disk() to work with remote database
def __init__(self, dbctx):
self.dbctx = dbctx
def cover(self, book_id):
return self.dbctx.run('export', 'cover', book_id)
def copy_format_to(self, book_id, fmt, path):
fdata = self.dbctx.run('export', 'fmt', book_id, fmt, path)
if self.dbctx.is_remote:
if fdata is None:
raise NoSuchFormat(fmt)
with lopen(path, 'wb') as f:
f.write(fdata)
def export(opts, dbctx, book_id, dest, dbproxy, length, first):
mi, plugboards, formats, library_id, template_funcs = dbctx.run(
'export', 'setup', book_id, opts.formats
)
if dbctx.is_remote and first:
load_user_template_functions(library_id, template_funcs)
return do_save_book_to_disk(
dbproxy, book_id, mi, plugboards, formats, dest, opts, length
)
def main(opts, args, dbctx): def main(opts, args, dbctx):
raise NotImplementedError('TODO: implement this') if len(args) < 1 and not opts.all:
raise SystemExit(_('You must specify some ids or the %s option') % '--all')
if opts.all:
book_ids = dbctx.run('export', 'all_ids')
else:
book_ids = set()
for arg in args:
book_ids |= set(integers_from_string(arg))
dest = os.path.abspath(os.path.expanduser(opts.to_dir))
dbproxy = DBProxy(dbctx)
dest, opts, length = sanitize_args(dest, opts)
for i, book_id in enumerate(book_ids):
export(opts, dbctx, book_id, dest, dbproxy, length, i == 0)
return 0 return 0

View File

@ -7,7 +7,6 @@ __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import os, traceback, re, errno import os, traceback, re, errno
from io import BytesIO
from calibre.constants import DEBUG from calibre.constants import DEBUG
from calibre.db.errors import NoSuchFormat from calibre.db.errors import NoSuchFormat
@ -258,12 +257,12 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250,
return shorten_components_to(length, components, last_has_extension=last_has_extension) return shorten_components_to(length, components, last_has_extension=last_has_extension)
def get_formats(available_formats, opts): def get_formats(available_formats, formats):
available_formats = {x.lower().strip() for x in available_formats} available_formats = {x.lower().strip() for x in available_formats}
if opts.formats == 'all': if formats == 'all':
asked_formats = available_formats asked_formats = available_formats
else: else:
asked_formats = {x.lower().strip() for x in opts.formats.split(',')} asked_formats = {x.lower().strip() for x in formats.split(',')}
return available_formats & asked_formats return available_formats & asked_formats
@ -271,7 +270,7 @@ def save_book_to_disk(book_id, db, root, opts, length):
db = db.new_api db = db.new_api
mi = db.get_metadata(book_id, index_is_id=True) mi = db.get_metadata(book_id, index_is_id=True)
plugboards = db.pref('plugboards', {}) plugboards = db.pref('plugboards', {})
formats = get_formats(db.formats(book_id), opts) formats = get_formats(db.formats(book_id), opts.formats)
return do_save_book_to_disk(db, book_id, mi, plugboards, return do_save_book_to_disk(db, book_id, mi, plugboards,
formats, root, opts, length) formats, root, opts, length)
@ -342,9 +341,8 @@ def do_save_book_to_disk(db, book_id, mi, plugboards,
cdata = None cdata = None
if opts.save_cover or formats: if opts.save_cover or formats:
cbuf = BytesIO() cdata = db.cover(book_id)
if db.copy_cover_to(book_id, cbuf): if cdata:
cdata = cbuf.getvalue()
cpath = base_path + '.jpg' cpath = base_path + '.jpg'
with lopen(cpath, 'wb') as f: with lopen(cpath, 'wb') as f:
f.write(cdata) f.write(cdata)
@ -368,7 +366,7 @@ def do_save_book_to_disk(db, book_id, mi, plugboards,
except NoSuchFormat: except NoSuchFormat:
continue continue
if opts.update_metadata: if opts.update_metadata:
with lopen(fmt_path, 'rb') as stream: with lopen(fmt_path, 'r+b') as stream:
update_metadata(mi, fmt, stream, plugboards, cdata) update_metadata(mi, fmt, stream, plugboards, cdata)
return not formats_written, book_id, mi.title return not formats_written, book_id, mi.title