From 3c4330ba510aa31bb60e58c00a24226225576a73 Mon Sep 17 00:00:00 2001 From: Thore Schillmann Date: Tue, 21 Jun 2022 17:04:44 +0000 Subject: [PATCH] refactoring of calibre binary detection --- cps/admin.py | 1 + cps/config_sql.py | 55 +++++++++++++++++++++++++++------- cps/constants.py | 3 ++ cps/tasks/convert.py | 7 +++-- cps/templates/config_edit.html | 7 +++++ 5 files changed, 60 insertions(+), 13 deletions(-) diff --git a/cps/admin.py b/cps/admin.py index 76275922..43103eed 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -1721,6 +1721,7 @@ def _configuration_update_helper(): constants.EXTENSIONS_UPLOAD = config.config_upload_formats.split(',') _config_string(to_save, "config_calibre") + _config_string(to_save, "config_binariesdir") _config_string(to_save, "config_converterpath") _config_string(to_save, "config_kepubifypath") diff --git a/cps/config_sql.py b/cps/config_sql.py index 743b2ce7..9e3472bd 100644 --- a/cps/config_sql.py +++ b/cps/config_sql.py @@ -131,6 +131,7 @@ class _Settings(_Base): config_kepubifypath = Column(String, default=None) config_converterpath = Column(String, default=None) + config_binariesdir = Column(String, default=None) config_calibre = Column(String) config_rarfile_location = Column(String, default=None) config_upload_formats = Column(String, default=','.join(constants.EXTENSIONS_UPLOAD)) @@ -166,12 +167,16 @@ class _ConfigSQL(object): self.cli = cli 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 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 - change = True self.config_kepubifypath = autodetect_kepubify_binary() @@ -266,6 +271,21 @@ class _ConfigSQL(object): def get_scheduled_task_settings(self): 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): """Possibly updates a field of this object. The new value, if present, is grabbed from the given dictionary, and optionally passed through a convertor. @@ -407,17 +427,31 @@ def _migrate_table(session, orm_class): session.rollback() -def autodetect_calibre_binary(): +def autodetect_calibre_binaries(): if sys.platform == "win32": - calibre_path = ["C:\\program files\\calibre\\ebook-convert.exe", - "C:\\program files(x86)\\calibre\\ebook-convert.exe", - "C:\\program files(x86)\\calibre2\\ebook-convert.exe", - "C:\\program files\\calibre2\\ebook-convert.exe"] + extension = ".exe" + calibre_path = ["C:\\program files\\calibre\\", + "C:\\program files(x86)\\calibre\\", + "C:\\program files(x86)\\calibre2\\", + "C:\\program files\\calibre2\\"] else: - calibre_path = ["/opt/calibre/ebook-convert"] + extension = "" + calibre_path = ["/opt/calibre/"] for element in calibre_path: - if os.path.isfile(element) and os.access(element, os.X_OK): - return element + 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 "" + + +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 "" @@ -462,6 +496,7 @@ def load_configuration(conf, session, cli): conf.init_config(session, cli) # return conf + def get_flask_session_key(_session): flask_settings = _session.query(_Flask_Settings).one_or_none() if flask_settings == None: diff --git a/cps/constants.py b/cps/constants.py index 0f3b2530..c684453c 100644 --- a/cps/constants.py +++ b/cps/constants.py @@ -152,6 +152,9 @@ EXTENSIONS_UPLOAD = {'txt', 'pdf', 'epub', 'kepub', 'mobi', 'azw', 'azw3', 'cbr' 'opus', 'wav', 'flac', 'm4a', 'm4b'} +SUPPORTED_CALIBRE_BINARIES = ["ebook-convert", "calibredb"] + + def has_flag(value, bit_flag): return bit_flag == (bit_flag & (value or 0)) diff --git a/cps/tasks/convert.py b/cps/tasks/convert.py index 6d723ac8..74455837 100644 --- a/cps/tasks/convert.py +++ b/cps/tasks/convert.py @@ -235,10 +235,11 @@ class TaskConvert(CalibreTask): # separate handling for windows and linux 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') - path_calibrecli = os.path.join(os.path.dirname(config.config_converterpath), "calibredb") - opf_command = [path_calibrecli, 'show_metadata', '--as-opf', str(book_id), '--with-library', config.config_calibre_dir] + calibredb_binarypath = config.get_calibre_binarypath("calibredb") + opf_command = [calibredb_binarypath, 'show_metadata', '--as-opf', str(book_id), '--with-library', config.config_calibre_dir] p = process_open(opf_command) path_tmp_opf = os.path.join(tmp_dir, "metadata_" + str(current_milli_time()) + ".opf") with open(path_tmp_opf, 'w') as fd: diff --git a/cps/templates/config_edit.html b/cps/templates/config_edit.html index f61ca9a5..725fb88d 100644 --- a/cps/templates/config_edit.html +++ b/cps/templates/config_edit.html @@ -323,6 +323,13 @@
+ +
+ + + + +