refactoring of calibre binary detection

This commit is contained in:
Thore Schillmann 2022-06-21 17:04:44 +00:00
parent 8c781ad4a4
commit 3c4330ba51
5 changed files with 60 additions and 13 deletions

View File

@ -1721,6 +1721,7 @@ def _configuration_update_helper():
constants.EXTENSIONS_UPLOAD = config.config_upload_formats.split(',') constants.EXTENSIONS_UPLOAD = config.config_upload_formats.split(',')
_config_string(to_save, "config_calibre") _config_string(to_save, "config_calibre")
_config_string(to_save, "config_binariesdir")
_config_string(to_save, "config_converterpath") _config_string(to_save, "config_converterpath")
_config_string(to_save, "config_kepubifypath") _config_string(to_save, "config_kepubifypath")

View File

@ -131,6 +131,7 @@ class _Settings(_Base):
config_kepubifypath = Column(String, default=None) config_kepubifypath = Column(String, default=None)
config_converterpath = Column(String, default=None) config_converterpath = Column(String, default=None)
config_binariesdir = Column(String, default=None)
config_calibre = Column(String) config_calibre = Column(String)
config_rarfile_location = Column(String, default=None) config_rarfile_location = Column(String, default=None)
config_upload_formats = Column(String, default=','.join(constants.EXTENSIONS_UPLOAD)) config_upload_formats = Column(String, default=','.join(constants.EXTENSIONS_UPLOAD))
@ -166,12 +167,16 @@ class _ConfigSQL(object):
self.cli = cli self.cli = cli
change = False change = False
if self.config_binariesdir == None: # pylint: disable=access-member-before-definition
change = True
self.config_binariesdir = autodetect_calibre_binaries()
if self.config_converterpath == None: # pylint: disable=access-member-before-definition if self.config_converterpath == None: # pylint: disable=access-member-before-definition
change = True change = True
self.config_converterpath = autodetect_calibre_binary() self.config_converterpath = autodetect_converter_binary()
if self.config_kepubifypath == None: # pylint: disable=access-member-before-definition if self.config_kepubifypath == None: # pylint: disable=access-member-before-definition
change = True change = True
self.config_kepubifypath = autodetect_kepubify_binary() self.config_kepubifypath = autodetect_kepubify_binary()
@ -266,6 +271,21 @@ class _ConfigSQL(object):
def get_scheduled_task_settings(self): def get_scheduled_task_settings(self):
return {k:v for k, v in self.__dict__.items() if k.startswith('schedule_')} return {k:v for k, v in self.__dict__.items() if k.startswith('schedule_')}
def get_calibre_binarypath(self, binary):
binariesdir = self.config_binariesdir
if binariesdir:
# TODO: Need to make sure that all supported calibre binaries are actually in the specified directory when set via UI
if sys.platform == "win32":
extension = ".exe"
else:
extension = ""
if binary in constants.SUPPORTED_CALIBRE_BINARIES:
return os.path.join(binariesdir, binary + extension)
else:
# TODO: Error handling
pass
return ""
def set_from_dictionary(self, dictionary, field, convertor=None, default=None, encode=None): def set_from_dictionary(self, dictionary, field, convertor=None, default=None, encode=None):
"""Possibly updates a field of this object. """Possibly updates a field of this object.
The new value, if present, is grabbed from the given dictionary, and optionally passed through a convertor. The new value, if present, is grabbed from the given dictionary, and optionally passed through a convertor.
@ -407,20 +427,34 @@ def _migrate_table(session, orm_class):
session.rollback() session.rollback()
def autodetect_calibre_binary(): def autodetect_calibre_binaries():
if sys.platform == "win32": if sys.platform == "win32":
calibre_path = ["C:\\program files\\calibre\\ebook-convert.exe", extension = ".exe"
"C:\\program files(x86)\\calibre\\ebook-convert.exe", calibre_path = ["C:\\program files\\calibre\\",
"C:\\program files(x86)\\calibre2\\ebook-convert.exe", "C:\\program files(x86)\\calibre\\",
"C:\\program files\\calibre2\\ebook-convert.exe"] "C:\\program files(x86)\\calibre2\\",
"C:\\program files\\calibre2\\"]
else: else:
calibre_path = ["/opt/calibre/ebook-convert"] extension = ""
calibre_path = ["/opt/calibre/"]
for element in calibre_path: for element in calibre_path:
if os.path.isfile(element) and os.access(element, os.X_OK): supported_binary_paths = [os.path.join(element, binary + extension) for binary in constants.SUPPORTED_CALIBRE_BINARIES]
if all(os.path.isfile(binary_path) and os.access(binary_path, os.X_OK) for binary_path in supported_binary_paths):
return element return element
return "" return ""
def autodetect_converter_binary():
calibre_path = autodetect_calibre_binaries()
if sys.platform == "win32":
converter_path = os.path.join(calibre_path, "ebook-convert.exe")
else:
converter_path = os.path.join(calibre_path, "ebook-convert")
if os.path.isfile(converter_path) and os.access(converter_path, os.X_OK):
return converter_path
return ""
def autodetect_unrar_binary(): def autodetect_unrar_binary():
if sys.platform == "win32": if sys.platform == "win32":
calibre_path = ["C:\\program files\\WinRar\\unRAR.exe", calibre_path = ["C:\\program files\\WinRar\\unRAR.exe",
@ -462,6 +496,7 @@ def load_configuration(conf, session, cli):
conf.init_config(session, cli) conf.init_config(session, cli)
# return conf # return conf
def get_flask_session_key(_session): def get_flask_session_key(_session):
flask_settings = _session.query(_Flask_Settings).one_or_none() flask_settings = _session.query(_Flask_Settings).one_or_none()
if flask_settings == None: if flask_settings == None:

View File

@ -152,6 +152,9 @@ EXTENSIONS_UPLOAD = {'txt', 'pdf', 'epub', 'kepub', 'mobi', 'azw', 'azw3', 'cbr'
'opus', 'wav', 'flac', 'm4a', 'm4b'} 'opus', 'wav', 'flac', 'm4a', 'm4b'}
SUPPORTED_CALIBRE_BINARIES = ["ebook-convert", "calibredb"]
def has_flag(value, bit_flag): def has_flag(value, bit_flag):
return bit_flag == (bit_flag & (value or 0)) return bit_flag == (bit_flag & (value or 0))

View File

@ -235,10 +235,11 @@ class TaskConvert(CalibreTask):
# separate handling for windows and linux # separate handling for windows and linux
quotes = [1, 2] quotes = [1, 2]
# TODO: Clean up and make cli work with windows. # TODO: Clean up.
# TODO: Maybe delete/clean-up tmp files directly.
tmp_dir = os.path.join(gettempdir(), 'calibre_web') tmp_dir = os.path.join(gettempdir(), 'calibre_web')
path_calibrecli = os.path.join(os.path.dirname(config.config_converterpath), "calibredb") calibredb_binarypath = config.get_calibre_binarypath("calibredb")
opf_command = [path_calibrecli, 'show_metadata', '--as-opf', str(book_id), '--with-library', config.config_calibre_dir] opf_command = [calibredb_binarypath, 'show_metadata', '--as-opf', str(book_id), '--with-library', config.config_calibre_dir]
p = process_open(opf_command) p = process_open(opf_command)
path_tmp_opf = os.path.join(tmp_dir, "metadata_" + str(current_milli_time()) + ".opf") path_tmp_opf = os.path.join(tmp_dir, "metadata_" + str(current_milli_time()) + ".opf")
with open(path_tmp_opf, 'w') as fd: with open(path_tmp_opf, 'w') as fd:

View File

@ -323,6 +323,13 @@
</div> </div>
<div id="collapsefive" class="panel-collapse collapse"> <div id="collapsefive" class="panel-collapse collapse">
<div class="panel-body"> <div class="panel-body">
<label for="config_binariesdir">{{_('Path to Calibre Binaries')}}</label>
<div class="form-group input-group">
<input type="text" class="form-control" id="config_binariesdir" name="config_binariesdir" value="{% if config.config_binariesdir != None %}{{ config.config_binariesdir }}{% endif %}" autocomplete="off">
<span class="input-group-btn">
<button type="button" data-toggle="modal" id="binaries_modal_path" data-link="config_binariesdir" data-target="#fileModal" class="btn btn-default"><span class="glyphicon glyphicon-folder-open"></span></button>
</span>
</div>
<label for="config_converterpath">{{_('Path to Calibre E-Book Converter')}}</label> <label for="config_converterpath">{{_('Path to Calibre E-Book Converter')}}</label>
<div class="form-group input-group"> <div class="form-group input-group">
<input type="text" class="form-control" id="config_converterpath" name="config_converterpath" value="{% if config.config_converterpath != None %}{{ config.config_converterpath }}{% endif %}" autocomplete="off"> <input type="text" class="form-control" id="config_converterpath" name="config_converterpath" value="{% if config.config_converterpath != None %}{{ config.config_converterpath }}{% endif %}" autocomplete="off">