Run explode/rebuild of MOBI in worker process to ensure no mem leaks

This commit is contained in:
Kovid Goyal 2012-05-01 12:51:29 +05:30
parent aca765c3d0
commit b27e06120c
2 changed files with 33 additions and 15 deletions

View File

@ -19,10 +19,21 @@ from calibre.ebooks.mobi.reader.mobi8 import Mobi8Reader
from calibre.ebooks.conversion.plumber import Plumber, create_oebbook from calibre.ebooks.conversion.plumber import Plumber, create_oebbook
from calibre.customize.ui import (plugin_for_input_format, from calibre.customize.ui import (plugin_for_input_format,
plugin_for_output_format) plugin_for_output_format)
from calibre.utils.ipc.simple_worker import fork_job
class BadFormat(ValueError): class BadFormat(ValueError):
pass pass
def do_explode(path, dest):
with open(path, 'rb') as stream:
mr = MobiReader(stream, default_log, None, None)
with CurrentDir(dest):
mr = Mobi8Reader(mr, default_log)
opf = os.path.abspath(mr())
return opf
def explode(path, dest, question=lambda x:True): def explode(path, dest, question=lambda x:True):
with open(path, 'rb') as stream: with open(path, 'rb') as stream:
raw = stream.read(3) raw = stream.read(3)
@ -50,21 +61,10 @@ def explode(path, dest, question=lambda x:True):
'sure?')): 'sure?')):
return None return None
return fork_job('calibre.ebooks.mobi.tweak', 'do_explode', args=(path,
dest), no_output=True)['result']
stream.seek(0) def do_rebuild(opf, dest_path):
mr = MobiReader(stream, default_log, None, None)
with CurrentDir(dest):
mr = Mobi8Reader(mr, default_log)
opf = os.path.abspath(mr())
return opf
def rebuild(src_dir, dest_path):
opf = glob.glob(os.path.join(src_dir, '*.opf'))
if not opf:
raise ValueError('No OPF file found in %s'%src_dir)
opf = opf[0]
plumber = Plumber(opf, dest_path, default_log) plumber = Plumber(opf, dest_path, default_log)
plumber.setup_options() plumber.setup_options()
inp = plugin_for_input_format('azw3') inp = plugin_for_input_format('azw3')
@ -74,4 +74,11 @@ def rebuild(src_dir, dest_path):
oeb = create_oebbook(default_log, opf, plumber.opts) oeb = create_oebbook(default_log, opf, plumber.opts)
outp.convert(oeb, dest_path, inp, plumber.opts, default_log) outp.convert(oeb, dest_path, inp, plumber.opts, default_log)
def rebuild(src_dir, dest_path):
opf = glob.glob(os.path.join(src_dir, '*.opf'))
if not opf:
raise ValueError('No OPF file found in %s'%src_dir)
opf = opf[0]
fork_job('calibre.ebooks.mobi.tweak', 'do_rebuild', args=(opf, dest_path),
no_output=True)

View File

@ -14,6 +14,7 @@ from calibre.constants import iswindows, __appname__
from calibre.ptempfile import TemporaryDirectory 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
class Error(ValueError): class Error(ValueError):
pass pass
@ -95,6 +96,10 @@ def tweak(ebook_file):
os.path.basename(ebook_file).rpartition('.')[0]) as tdir: os.path.basename(ebook_file).rpartition('.')[0]) as tdir:
try: try:
opf = exploder(ebook_file, tdir, question=ask_cli_question) opf = exploder(ebook_file, tdir, 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: except Error as e:
prints(as_unicode(e), file=sys.stderr) prints(as_unicode(e), file=sys.stderr)
raise SystemExit(1) raise SystemExit(1)
@ -121,6 +126,12 @@ def tweak(ebook_file):
proceed = True proceed = True
if proceed: if proceed:
rebuilder(tdir, ebook_file) prints('Rebuilding', ebook_file, 'please wait ...')
try:
rebuilder(tdir, ebook_file)
except WorkerError as e:
prints('Failed to rebuild', ebook_file)
prints(e.orig_tb)
raise SystemExit(1)
prints(ebook_file, 'successfully tweaked') prints(ebook_file, 'successfully tweaked')