mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
calibre-debug: Change the --explode-book action to only create the exploded directory and not rebuild the file. Add a new --implode-book action to rebuild the file, separately.
This commit is contained in:
parent
51caa0ea04
commit
224921792e
@ -82,12 +82,17 @@ Everything after the -- is passed to the script.
|
|||||||
help=_('Inspect the MOBI file(s) at the specified path(s)'))
|
help=_('Inspect the MOBI file(s) at the specified path(s)'))
|
||||||
parser.add_option('-t', '--edit-book', action='store_true',
|
parser.add_option('-t', '--edit-book', action='store_true',
|
||||||
help=_('Launch the calibre "Edit book" tool in debug mode.'))
|
help=_('Launch the calibre "Edit book" tool in debug mode.'))
|
||||||
parser.add_option('-x', '--explode-book', default=None,
|
parser.add_option('-x', '--explode-book', default=False, action='store_true',
|
||||||
help=_('Explode the book (exports the book as a collection of HTML '
|
help=_('Explode the book into the specified directory.\nUsage: '
|
||||||
|
'-x file.epub output_dir\n'
|
||||||
|
'Exports the book as a collection of HTML '
|
||||||
'files and metadata, which you can edit using standard HTML '
|
'files and metadata, which you can edit using standard HTML '
|
||||||
'editing tools, and then rebuilds the file from the edited HTML. '
|
'editing tools. Works with EPUB, AZW3, HTMLZ and DOCX files.'))
|
||||||
'Makes no additional changes to the HTML, unlike a full calibre '
|
parser.add_option('-i', '--implode-book', default=False, action='store_true', help=_(
|
||||||
'conversion).'))
|
'Implode a previously exploded book.\nUsage: -i output_dir file.epub\n'
|
||||||
|
'Imports the book from the files in output_dir which must have'
|
||||||
|
' been created by a previous call to --explode-book. Be sure to'
|
||||||
|
' specify the same file type as was used when exploding.'))
|
||||||
parser.add_option('--export-all-calibre-data', default=False, action='store_true',
|
parser.add_option('--export-all-calibre-data', default=False, action='store_true',
|
||||||
help=_('Export all calibre data (books/settings/plugins)'))
|
help=_('Export all calibre data (books/settings/plugins)'))
|
||||||
parser.add_option('--import-calibre-data', default=False, action='store_true',
|
parser.add_option('--import-calibre-data', default=False, action='store_true',
|
||||||
@ -277,9 +282,14 @@ def main(args=sys.argv):
|
|||||||
elif opts.edit_book:
|
elif opts.edit_book:
|
||||||
from calibre.gui_launch import ebook_edit
|
from calibre.gui_launch import ebook_edit
|
||||||
ebook_edit(['ebook-edit'] + args[1:])
|
ebook_edit(['ebook-edit'] + args[1:])
|
||||||
elif opts.explode_book:
|
elif opts.explode_book or opts.implode_book:
|
||||||
from calibre.ebooks.tweak import tweak
|
from calibre.ebooks.tweak import explode, implode
|
||||||
tweak(opts.explode_book)
|
try:
|
||||||
|
a1, a2 = args[1:]
|
||||||
|
except Exception:
|
||||||
|
raise SystemExit('Must provide exactly two arguments')
|
||||||
|
f = explode if opts.explode_book else implode
|
||||||
|
f(a1, a2)
|
||||||
elif opts.test_build:
|
elif opts.test_build:
|
||||||
from calibre.test_build import test
|
from calibre.test_build import test
|
||||||
test()
|
test()
|
||||||
|
@ -7,11 +7,11 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import sys, os, shlex, subprocess, shutil, unicodedata
|
import sys, os, unicodedata
|
||||||
|
|
||||||
from calibre import prints, as_unicode, walk
|
from calibre import prints, as_unicode, walk
|
||||||
from calibre.constants import iswindows, __appname__
|
from calibre.constants import iswindows, __appname__
|
||||||
from calibre.ptempfile import TemporaryDirectory, TemporaryFile
|
from calibre.ptempfile import TemporaryDirectory
|
||||||
from calibre.libunzip import extract as zipextract
|
from calibre.libunzip import extract as zipextract
|
||||||
from calibre.utils.zipfile import ZipFile, ZIP_DEFLATED, ZIP_STORED
|
from calibre.utils.zipfile import ZipFile, ZIP_DEFLATED, ZIP_STORED
|
||||||
from calibre.utils.ipc.simple_worker import WorkerError
|
from calibre.utils.ipc.simple_worker import WorkerError
|
||||||
@ -102,6 +102,61 @@ def get_tools(fmt):
|
|||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
def explode(ebook_file, output_dir):
|
||||||
|
if not os.path.exists(output_dir):
|
||||||
|
os.makedirs(output_dir)
|
||||||
|
if not os.path.isdir(output_dir):
|
||||||
|
raise SystemExit('%s is not a directory' % output_dir)
|
||||||
|
output_dir = os.path.abspath(output_dir)
|
||||||
|
fmt = ebook_file.rpartition('.')[-1].lower()
|
||||||
|
exploder, rebuilder = get_tools(fmt)
|
||||||
|
if exploder is None:
|
||||||
|
raise SystemExit('Cannot tweak %s files. Supported formats are: EPUB, HTMLZ, AZW3, MOBI, DOCX' % fmt.upper())
|
||||||
|
try:
|
||||||
|
opf = exploder(ebook_file, output_dir, question=ask_cli_question)
|
||||||
|
except WorkerError as e:
|
||||||
|
prints('Failed to unpack', ebook_file)
|
||||||
|
prints(e.orig_tb)
|
||||||
|
raise SystemExit(1)
|
||||||
|
except Error as e:
|
||||||
|
prints(as_unicode(e), file=sys.stderr)
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
if opf is None:
|
||||||
|
# The question was answered with No
|
||||||
|
return
|
||||||
|
h = '_' if iswindows else '.'
|
||||||
|
with lopen(os.path.join(output_dir, h + '__explode_fmt__'), 'wb') as f:
|
||||||
|
f.write(fmt)
|
||||||
|
prints('Book extracted to', output_dir)
|
||||||
|
prints('Make your changes and once you are done, use --implode-book to rebuild')
|
||||||
|
|
||||||
|
|
||||||
|
def implode(output_dir, ebook_file):
|
||||||
|
output_dir = os.path.abspath(output_dir)
|
||||||
|
fmt = ebook_file.rpartition('.')[-1].lower()
|
||||||
|
exploder, rebuilder = get_tools(fmt)
|
||||||
|
if rebuilder is None:
|
||||||
|
raise SystemExit('Cannot tweak %s files. Supported formats are: EPUB, HTMLZ, AZW3, MOBI, DOCX' % fmt.upper())
|
||||||
|
h = '_' if iswindows else '.'
|
||||||
|
efmt_path = os.path.join(output_dir, h + '__explode_fmt__')
|
||||||
|
try:
|
||||||
|
with lopen(efmt_path, 'rb') as f:
|
||||||
|
efmt = f.read()
|
||||||
|
except Exception:
|
||||||
|
raise SystemExit('The directory %s does not seem to have been created by --explode-book' % output_dir)
|
||||||
|
if efmt != fmt:
|
||||||
|
raise SystemExit('You must use the same format of file as was used when exploding the book')
|
||||||
|
os.remove(efmt_path)
|
||||||
|
try:
|
||||||
|
rebuilder(output_dir, ebook_file)
|
||||||
|
except WorkerError as e:
|
||||||
|
prints('Failed to rebuild', ebook_file)
|
||||||
|
prints(e.orig_tb)
|
||||||
|
raise SystemExit(1)
|
||||||
|
prints(ebook_file, 'successfully rebuilt')
|
||||||
|
|
||||||
|
|
||||||
def tweak(ebook_file):
|
def tweak(ebook_file):
|
||||||
''' Command line interface to the Tweak Book tool '''
|
''' Command line interface to the Tweak Book tool '''
|
||||||
fmt = ebook_file.rpartition('.')[-1].lower()
|
fmt = ebook_file.rpartition('.')[-1].lower()
|
||||||
@ -127,33 +182,11 @@ def tweak(ebook_file):
|
|||||||
# The question was answered with No
|
# The question was answered with No
|
||||||
return
|
return
|
||||||
|
|
||||||
ed = os.environ.get('EDITOR', 'dummy')
|
|
||||||
cmd = shlex.split(ed)
|
|
||||||
isvim = bool([x for x in cmd[0].split('/') if x.endswith('vim')])
|
|
||||||
|
|
||||||
proceed = False
|
|
||||||
prints('Book extracted to', tdir)
|
prints('Book extracted to', tdir)
|
||||||
|
prints('Make your tweaks and once you are done,', __appname__,
|
||||||
if not isvim:
|
'will rebuild', ebook_file, 'from', tdir)
|
||||||
prints('Make your tweaks and once you are done,', __appname__,
|
print()
|
||||||
'will rebuild', ebook_file, 'from', tdir)
|
proceed = ask_cli_question('Rebuild ' + ebook_file + '?')
|
||||||
print()
|
|
||||||
proceed = ask_cli_question('Rebuild ' + ebook_file + '?')
|
|
||||||
else:
|
|
||||||
base = os.path.basename(ebook_file)
|
|
||||||
with TemporaryFile(base+'.zip') as zipf:
|
|
||||||
with ZipFile(zipf, 'w') as zf:
|
|
||||||
zf.add_dir(tdir)
|
|
||||||
try:
|
|
||||||
subprocess.check_call(cmd + [zipf])
|
|
||||||
except:
|
|
||||||
prints(ed, 'failed, aborting...')
|
|
||||||
raise SystemExit(1)
|
|
||||||
with ZipFile(zipf, 'r') as zf:
|
|
||||||
shutil.rmtree(tdir)
|
|
||||||
os.mkdir(tdir)
|
|
||||||
zf.extractall(path=tdir)
|
|
||||||
proceed = True
|
|
||||||
|
|
||||||
if proceed:
|
if proceed:
|
||||||
prints('Rebuilding', ebook_file, 'please wait ...')
|
prints('Rebuilding', ebook_file, 'please wait ...')
|
||||||
@ -164,4 +197,3 @@ def tweak(ebook_file):
|
|||||||
prints(e.orig_tb)
|
prints(e.orig_tb)
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
prints(ebook_file, 'successfully tweaked')
|
prints(ebook_file, 'successfully tweaked')
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user