mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Fix memory leak when queueing books for bulk convert
This commit is contained in:
parent
a4dd30cea5
commit
a1b42542e1
@ -18,6 +18,24 @@ from calibre.ebooks.metadata.opf2 import OPFCreator
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
from calibre.gui2.convert import Widget
|
||||
|
||||
def create_opf_file(db, book_id):
|
||||
mi = db.get_metadata(book_id, index_is_id=True)
|
||||
mi.application_id = uuid.uuid4()
|
||||
opf = OPFCreator(os.getcwdu(), mi)
|
||||
opf_file = PersistentTemporaryFile('.opf')
|
||||
opf.render(opf_file)
|
||||
opf_file.close()
|
||||
return mi, opf_file
|
||||
|
||||
def create_cover_file(db, book_id):
|
||||
cover = db.cover(book_id, index_is_id=True)
|
||||
cf = None
|
||||
if cover:
|
||||
cf = PersistentTemporaryFile('.jpeg')
|
||||
cf.write(cover)
|
||||
cf.close()
|
||||
return cf
|
||||
|
||||
class MetadataWidget(Widget, Ui_Form):
|
||||
|
||||
TITLE = _('Metadata')
|
||||
@ -181,12 +199,7 @@ class MetadataWidget(Widget, Ui_Form):
|
||||
self.cover_file = self.opf_file = None
|
||||
if self.db is not None:
|
||||
self.db.set_metadata(self.book_id, self.user_mi)
|
||||
self.mi = self.db.get_metadata(self.book_id, index_is_id=True)
|
||||
self.mi.application_id = uuid.uuid4()
|
||||
opf = OPFCreator(os.getcwdu(), self.mi)
|
||||
self.opf_file = PersistentTemporaryFile('.opf')
|
||||
opf.render(self.opf_file)
|
||||
self.opf_file.close()
|
||||
self.mi, self.opf_file = create_opf_file(self.db, self.book_id)
|
||||
if self.cover_changed and self.cover_data is not None:
|
||||
self.db.set_cover(self.book_id, self.cover_data)
|
||||
cover = self.db.cover(self.book_id, index_is_id=True)
|
||||
|
@ -68,6 +68,36 @@ class GroupModel(QAbstractListModel):
|
||||
return QVariant(f)
|
||||
return NONE
|
||||
|
||||
def get_preferred_input_format_for_book(db, book_id):
|
||||
recs = load_specifics(db, book_id)
|
||||
if recs:
|
||||
return recs.get('gui_preferred_input_format', None)
|
||||
|
||||
def get_available_formats_for_book(db, book_id):
|
||||
available_formats = db.formats(book_id, index_is_id=True)
|
||||
if not available_formats:
|
||||
available_formats = ''
|
||||
return set([x.lower() for x in
|
||||
available_formats.split(',')])
|
||||
|
||||
def get_supported_input_formats_for_book(db, book_id):
|
||||
available_formats = get_available_formats_for_book(db, book_id)
|
||||
input_formats = set([x.lower() for x in supported_input_formats()])
|
||||
input_formats = sorted(available_formats.intersection(input_formats))
|
||||
if not input_formats:
|
||||
raise NoSupportedInputFormats
|
||||
return input_formats
|
||||
|
||||
|
||||
def get_input_format_for_book(db, book_id, pref):
|
||||
if pref is None:
|
||||
pref = get_preferred_input_format_for_book(db, book_id)
|
||||
input_formats = get_supported_input_formats_for_book(db, book_id)
|
||||
input_format = pref if pref in input_formats else \
|
||||
sort_formats_by_preference(input_formats, prefs['input_format_order'])[0]
|
||||
return input_format, input_formats
|
||||
|
||||
|
||||
class Config(ResizableDialog, Ui_Dialog):
|
||||
'''
|
||||
Configuration dialog for single book conversion. If accepted, has the
|
||||
@ -86,12 +116,6 @@ class Config(ResizableDialog, Ui_Dialog):
|
||||
preferred_input_format=None, preferred_output_format=None):
|
||||
ResizableDialog.__init__(self, parent)
|
||||
|
||||
if preferred_input_format is None and db is not None:
|
||||
recs = load_specifics(db, book_id)
|
||||
if recs:
|
||||
preferred_input_format = recs.get('gui_preferred_input_format',
|
||||
None)
|
||||
|
||||
self.setup_input_output_formats(db, book_id, preferred_input_format,
|
||||
preferred_output_format)
|
||||
self.db, self.book_id = db, book_id
|
||||
@ -194,22 +218,10 @@ class Config(ResizableDialog, Ui_Dialog):
|
||||
preferred_output_format):
|
||||
if preferred_output_format:
|
||||
preferred_output_format = preferred_output_format.lower()
|
||||
available_formats = db.formats(book_id, index_is_id=True)
|
||||
if not available_formats:
|
||||
available_formats = ''
|
||||
available_formats = set([x.lower() for x in
|
||||
available_formats.split(',')])
|
||||
input_formats = set([x.lower() for x in supported_input_formats()])
|
||||
input_formats = \
|
||||
sorted(available_formats.intersection(input_formats))
|
||||
if not input_formats:
|
||||
raise NoSupportedInputFormats
|
||||
output_formats = sorted(available_output_formats())
|
||||
output_formats.remove('oeb')
|
||||
preferred_input_format = preferred_input_format if \
|
||||
preferred_input_format in input_formats else \
|
||||
sort_formats_by_preference(input_formats,
|
||||
prefs['input_format_order'])[0]
|
||||
input_format, input_formats = get_input_format_for_book(db, book_id,
|
||||
preferred_input_format)
|
||||
preferred_output_format = preferred_output_format if \
|
||||
preferred_output_format in output_formats else \
|
||||
sort_formats_by_preference(output_formats,
|
||||
@ -218,7 +230,7 @@ class Config(ResizableDialog, Ui_Dialog):
|
||||
input_formats])))
|
||||
self.output_formats.addItems(list(map(QString, [x.upper() for x in
|
||||
output_formats])))
|
||||
self.input_formats.setCurrentIndex(input_formats.index(preferred_input_format))
|
||||
self.input_formats.setCurrentIndex(input_formats.index(input_format))
|
||||
self.output_formats.setCurrentIndex(output_formats.index(preferred_output_format))
|
||||
|
||||
def show_pane(self, index):
|
||||
|
@ -14,8 +14,10 @@ from PyQt4.Qt import QDialog
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
from calibre.gui2 import warning_dialog, question_dialog
|
||||
from calibre.gui2.convert.single import NoSupportedInputFormats
|
||||
from calibre.gui2.convert.single import Config as SingleConfig
|
||||
from calibre.gui2.convert.single import Config as SingleConfig, \
|
||||
get_input_format_for_book
|
||||
from calibre.gui2.convert.bulk import BulkConfig
|
||||
from calibre.gui2.convert.metadata import create_opf_file, create_cover_file
|
||||
from calibre.customize.conversion import OptionRecommendation
|
||||
from calibre.utils.config import prefs
|
||||
from calibre.ebooks.conversion.config import GuiRecommendations, \
|
||||
@ -112,13 +114,11 @@ def convert_bulk_ebook(parent, db, book_ids, out_format=None):
|
||||
book_ids = convert_existing(parent, db, book_ids, output_format)
|
||||
for i, book_id in enumerate(book_ids):
|
||||
temp_files = []
|
||||
input_format = get_input_format_for_book(db, book_id, None)[0]
|
||||
|
||||
try:
|
||||
d = SingleConfig(parent, db, book_id, None, output_format)
|
||||
d.accept()
|
||||
|
||||
mi = db.get_metadata(book_id, True)
|
||||
in_file = db.format_abspath(book_id, d.input_format, True)
|
||||
mi, opf_file = create_opf_file(db, book_id)
|
||||
in_file = db.format_abspath(book_id, input_format, True)
|
||||
|
||||
out_file = PersistentTemporaryFile('.' + output_format)
|
||||
out_file.write(output_format)
|
||||
@ -126,7 +126,7 @@ def convert_bulk_ebook(parent, db, book_ids, out_format=None):
|
||||
temp_files = []
|
||||
|
||||
combined_recs = GuiRecommendations()
|
||||
default_recs = load_defaults('%s_input' % d.input_format)
|
||||
default_recs = load_defaults('%s_input' % input_format)
|
||||
specific_recs = load_specifics(db, book_id)
|
||||
for key in default_recs:
|
||||
combined_recs[key] = default_recs[key]
|
||||
@ -137,14 +137,16 @@ def convert_bulk_ebook(parent, db, book_ids, out_format=None):
|
||||
save_specifics(db, book_id, combined_recs)
|
||||
lrecs = list(combined_recs.to_recommendations())
|
||||
|
||||
if d.opf_file is not None:
|
||||
lrecs.append(('read_metadata_from_opf', d.opf_file.name,
|
||||
cover_file = create_cover_file(db, book_id)
|
||||
|
||||
if opf_file is not None:
|
||||
lrecs.append(('read_metadata_from_opf', opf_file.name,
|
||||
OptionRecommendation.HIGH))
|
||||
temp_files.append(d.opf_file)
|
||||
if d.cover_file is not None:
|
||||
lrecs.append(('cover', d.cover_file.name,
|
||||
temp_files.append(opf_file)
|
||||
if cover_file is not None:
|
||||
lrecs.append(('cover', cover_file.name,
|
||||
OptionRecommendation.HIGH))
|
||||
temp_files.append(d.cover_file)
|
||||
temp_files.append(cover_file)
|
||||
|
||||
for x in list(lrecs):
|
||||
if x[0] == 'debug_pipeline':
|
||||
@ -158,7 +160,7 @@ def convert_bulk_ebook(parent, db, book_ids, out_format=None):
|
||||
|
||||
args = [in_file, out_file.name, lrecs]
|
||||
temp_files.append(out_file)
|
||||
jobs.append(('gui_convert', args, desc, d.output_format.upper(), book_id, temp_files))
|
||||
jobs.append(('gui_convert', args, desc, output_format.upper(), book_id, temp_files))
|
||||
|
||||
changed = True
|
||||
except NoSupportedInputFormats:
|
||||
|
Loading…
x
Reference in New Issue
Block a user