1
0
mirror of https://github.com/janeczku/calibre-web synced 2024-12-26 01:50:31 +00:00

New restart routine for executable files

Fix log in updater
New source option updater available
This commit is contained in:
Ozzie Isaacs 2021-02-06 09:42:27 +01:00
parent 6137fdeb33
commit e6fb460071
7 changed files with 112 additions and 41 deletions

View File

@ -48,6 +48,11 @@ try:
except ImportError: except ImportError:
flask_danceVersion = None flask_danceVersion = None
try:
from greenlet import __version__ as greenlet_Version
except ImportError:
greenlet_Version = None
from . import services from . import services
about = flask.Blueprint('about', __name__) about = flask.Blueprint('about', __name__)
@ -77,7 +82,8 @@ _VERSIONS = OrderedDict(
python_LDAP = services.ldapVersion if bool(services.ldapVersion) else None, python_LDAP = services.ldapVersion if bool(services.ldapVersion) else None,
Goodreads = u'installed' if bool(services.goodreads_support) else None, Goodreads = u'installed' if bool(services.goodreads_support) else None,
jsonschema = services.SyncToken.__version__ if bool(services.SyncToken) else None, jsonschema = services.SyncToken.__version__ if bool(services.SyncToken) else None,
flask_dance = flask_danceVersion flask_dance = flask_danceVersion,
greenlet = greenlet_Version
) )
_VERSIONS.update(uploader.get_versions()) _VERSIONS.update(uploader.get_versions())

View File

@ -56,7 +56,8 @@ log = logger.create()
feature_support = { feature_support = {
'ldap': bool(services.ldap), 'ldap': bool(services.ldap),
'goodreads': bool(services.goodreads_support), 'goodreads': bool(services.goodreads_support),
'kobo': bool(services.kobo) 'kobo': bool(services.kobo),
'updater': constants.UPDATER_AVAILABLE
} }
try: try:
@ -1264,8 +1265,11 @@ def download_debug():
@login_required @login_required
@admin_required @admin_required
def get_update_status(): def get_update_status():
if feature_support['updater']:
log.info(u"Update status requested") log.info(u"Update status requested")
return updater_thread.get_available_updates(request.method, locale=get_locale()) return updater_thread.get_available_updates(request.method, locale=get_locale())
else:
return ''
@admi.route("/get_updater_status", methods=['GET', 'POST']) @admi.route("/get_updater_status", methods=['GET', 'POST'])
@ -1273,6 +1277,7 @@ def get_update_status():
@admin_required @admin_required
def get_updater_status(): def get_updater_status():
status = {} status = {}
if feature_support['updater']:
if request.method == "POST": if request.method == "POST":
commit = request.form.to_dict() commit = request.form.to_dict()
if "start" in commit and commit['start'] == 'True': if "start" in commit and commit['start'] == 'True':
@ -1302,6 +1307,7 @@ def get_updater_status():
except Exception: except Exception:
status['status'] = 11 status['status'] = 11
return json.dumps(status) return json.dumps(status)
return ''
@admi.route('/import_ldap_users') @admi.route('/import_ldap_users')

View File

@ -23,6 +23,7 @@ from collections import namedtuple
# if installed via pip this variable is set to true # if installed via pip this variable is set to true
HOME_CONFIG = False HOME_CONFIG = False
UPDATER_AVAILABLE = True
# Base dir is parent of current file, necessary if called from different folder # Base dir is parent of current file, necessary if called from different folder
if sys.version_info < (3, 0): if sys.version_info < (3, 0):

View File

@ -22,6 +22,7 @@ import os
import errno import errno
import signal import signal
import socket import socket
import subprocess
try: try:
from gevent.pywsgi import WSGIServer from gevent.pywsgi import WSGIServer
@ -136,6 +137,64 @@ class WebServer(object):
return sock, _readable_listen_address(*address) return sock, _readable_listen_address(*address)
def _get_args_for_reloading(self):
"""Determine how the script was executed, and return the args needed
to execute it again in a new process.
Code from https://github.com/pyload/pyload. Author GammaC0de, voulter
"""
rv = [sys.executable]
py_script = sys.argv[0]
args = sys.argv[1:]
# Need to look at main module to determine how it was executed.
__main__ = sys.modules["__main__"]
# The value of __package__ indicates how Python was called. It may
# not exist if a setuptools script is installed as an egg. It may be
# set incorrectly for entry points created with pip on Windows.
if getattr(__main__, "__package__", None) is None or (
os.name == "nt"
and __main__.__package__ == ""
and not os.path.exists(py_script)
and os.path.exists(f"{py_script}.exe")
):
# Executed a file, like "python app.py".
py_script = os.path.abspath(py_script)
if os.name == "nt":
# Windows entry points have ".exe" extension and should be
# called directly.
if not os.path.exists(py_script) and os.path.exists(f"{py_script}.exe"):
py_script += ".exe"
if (
os.path.splitext(sys.executable)[1] == ".exe"
and os.path.splitext(py_script)[1] == ".exe"
):
rv.pop(0)
rv.append(py_script)
else:
# Executed a module, like "python -m module".
if sys.argv[0] == "-m":
args = sys.argv
else:
if os.path.isfile(py_script):
# Rewritten by Python from "-m script" to "/path/to/script.py".
py_module = __main__.__package__
name = os.path.splitext(os.path.basename(py_script))[0]
if name != "__main__":
py_module += f".{name}"
else:
# Incorrectly rewritten by pydevd debugger from "-m script" to "script".
py_module = py_script
rv.extend(("-m", py_module.lstrip(".")))
rv.extend(args)
return rv
def _start_gevent(self): def _start_gevent(self):
ssl_args = self.ssl_args or {} ssl_args = self.ssl_args or {}
@ -199,11 +258,8 @@ class WebServer(object):
return True return True
log.info("Performing restart of Calibre-Web") log.info("Performing restart of Calibre-Web")
arguments = list(sys.argv) args = self._get_args_for_reloading()
arguments.insert(0, sys.executable) subprocess.call(args, close_fds=True)
if os.name == 'nt':
arguments = ["\"%s\"" % a for a in arguments]
os.execv(sys.executable, arguments)
return True return True
def _killServer(self, __, ___): def _killServer(self, __, ___):

View File

@ -168,9 +168,11 @@
</tbody> </tbody>
</table> </table>
{% if feature_support['updater'] %}
<div class="hidden" id="update_error"> <span>{{update_error}}</span></div> <div class="hidden" id="update_error"> <span>{{update_error}}</span></div>
<div class="btn btn-primary" id="check_for_update">{{_('Check for Update')}}</div> <div class="btn btn-primary" id="check_for_update">{{_('Check for Update')}}</div>
<div class="btn btn-primary hidden" id="perform_update" data-toggle="modal" data-target="#StatusDialog">{{_('Perform Update')}}</div> <div class="btn btn-primary hidden" id="perform_update" data-toggle="modal" data-target="#StatusDialog">{{_('Perform Update')}}</div>
{% endif %}
</div> </div>
</div> </div>
</div> </div>

View File

@ -264,7 +264,7 @@ class Updater(threading.Thread):
# log_from_thread("Delete file " + item_path) # log_from_thread("Delete file " + item_path)
os.remove(item_path) os.remove(item_path)
except OSError: except OSError:
logger.debug("Could not remove: %s", item_path) log.debug("Could not remove: %s", item_path)
shutil.rmtree(source, ignore_errors=True) shutil.rmtree(source, ignore_errors=True)
def is_venv(self): def is_venv(self):

View File

@ -1,7 +1,7 @@
# GDrive Integration # GDrive Integration
google-api-python-client>=1.7.11,<1.8.0 google-api-python-client>=1.7.11,<1.8.0
gevent>=1.2.1,<20.6.0 gevent>20.6.0,<21.2.0
greenlet>=0.4.12,<0.4.17 greenlet>=0.4.17,<1.1.0
httplib2>=0.9.2,<0.18.0 httplib2>=0.9.2,<0.18.0
oauth2client>=4.0.0,<4.1.4 oauth2client>=4.0.0,<4.1.4
uritemplate>=3.0.0,<3.1.0 uritemplate>=3.0.0,<3.1.0