Move backend initialization to config.py
This commit is contained in:
parent
01da144a03
commit
5298d14084
@ -77,7 +77,7 @@ def run(args):
|
||||
standarddir.init(args)
|
||||
|
||||
log.init.debug("Initializing config...")
|
||||
config.early_init()
|
||||
config.early_init(args)
|
||||
|
||||
global qApp
|
||||
qApp = Application(args)
|
||||
|
@ -29,7 +29,7 @@ from PyQt5.QtWidgets import QMessageBox
|
||||
|
||||
from qutebrowser.config import configdata, configexc, configtypes, configfiles
|
||||
from qutebrowser.utils import utils, objreg, message, log, usertypes, jinja
|
||||
from qutebrowser.misc import objects, msgbox
|
||||
from qutebrowser.misc import objects, msgbox, earlyinit
|
||||
from qutebrowser.commands import cmdexc, cmdutils, runners
|
||||
from qutebrowser.completion.models import configmodel
|
||||
|
||||
@ -641,7 +641,7 @@ class StyleSheetObserver(QObject):
|
||||
instance.changed.connect(self._update_stylesheet)
|
||||
|
||||
|
||||
def early_init():
|
||||
def early_init(args):
|
||||
"""Initialize the part of the config which works without a QApplication."""
|
||||
configdata.init()
|
||||
|
||||
@ -686,6 +686,30 @@ def early_init():
|
||||
|
||||
configfiles.init()
|
||||
|
||||
objects.backend = get_backend(args)
|
||||
earlyinit.init_with_backend(objects.backend)
|
||||
|
||||
|
||||
def get_backend(args):
|
||||
"""Find out what backend to use based on available libraries."""
|
||||
from qutebrowser.utils import usertypes
|
||||
try:
|
||||
import PyQt5.QtWebKit # pylint: disable=unused-variable
|
||||
webkit_available = True
|
||||
except ImportError:
|
||||
webkit_available = False
|
||||
|
||||
if args.backend is not None:
|
||||
backends = {
|
||||
'webkit': usertypes.Backend.QtWebKit,
|
||||
'webengine': usertypes.Backend.QtWebEngine,
|
||||
}
|
||||
return backends[args.backend]
|
||||
elif webkit_available:
|
||||
return usertypes.Backend.QtWebKit
|
||||
else:
|
||||
return usertypes.Backend.QtWebEngine
|
||||
|
||||
|
||||
def late_init(save_manager):
|
||||
"""Initialize the rest of the config after the QApplication is created."""
|
||||
|
@ -163,26 +163,6 @@ def check_pyqt_core():
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def get_backend(args):
|
||||
"""Find out what backend to use based on available libraries.
|
||||
|
||||
Note this function returns the backend as a string so we don't have to
|
||||
import qutebrowser.utils.usertypes yet.
|
||||
"""
|
||||
try:
|
||||
import PyQt5.QtWebKit # pylint: disable=unused-variable
|
||||
webkit_available = True
|
||||
except ImportError:
|
||||
webkit_available = False
|
||||
|
||||
if args.backend is not None:
|
||||
return args.backend
|
||||
elif webkit_available:
|
||||
return 'webkit'
|
||||
else:
|
||||
return 'webengine'
|
||||
|
||||
|
||||
def qt_version(qversion=None, qt_version_str=None):
|
||||
"""Get a Qt version string based on the runtime/compiled versions."""
|
||||
if qversion is None:
|
||||
@ -210,31 +190,52 @@ def check_qt_version():
|
||||
_die(text)
|
||||
|
||||
|
||||
def check_ssl_support(backend):
|
||||
def check_ssl_support():
|
||||
"""Check if SSL support is available."""
|
||||
from qutebrowser.utils import log
|
||||
|
||||
try:
|
||||
from PyQt5.QtNetwork import QSslSocket
|
||||
except ImportError:
|
||||
_die("Fatal error: Your Qt is built without SSL support.")
|
||||
|
||||
|
||||
def check_backend_ssl_support(backend):
|
||||
"""Check for full SSL availability when we know the backend."""
|
||||
from PyQt5.QtNetwork import QSslSocket
|
||||
from qutebrowser.utils import log, usertypes
|
||||
text = ("Could not initialize QtNetwork SSL support. If you use "
|
||||
"OpenSSL 1.1 with a PyQt package from PyPI (e.g. on Archlinux "
|
||||
"or Debian Stretch), you need to set LD_LIBRARY_PATH to the path "
|
||||
"of OpenSSL 1.0.")
|
||||
if backend == 'webengine':
|
||||
text += " This only affects downloads."
|
||||
"of OpenSSL 1.0. This only affects downloads.")
|
||||
|
||||
if not QSslSocket.supportsSsl():
|
||||
if backend == 'webkit':
|
||||
if backend == usertypes.Backend.QtWebKit:
|
||||
_die("Could not initialize SSL support.")
|
||||
else:
|
||||
assert backend == 'webengine'
|
||||
assert backend == usertypes.Backend.QtWebEngine
|
||||
log.init.warning(text)
|
||||
|
||||
|
||||
def check_libraries(backend):
|
||||
def _check_modules(modules):
|
||||
"""Make sure the given modules are available."""
|
||||
from qutebrowser.utils import log
|
||||
|
||||
for name, text in modules.items():
|
||||
try:
|
||||
# https://github.com/pallets/jinja/pull/628
|
||||
# https://bitbucket.org/birkenfeld/pygments-main/issues/1314/
|
||||
# https://github.com/pallets/jinja/issues/646
|
||||
# https://bitbucket.org/fdik/pypeg/commits/dd15ca462b532019c0a3be1d39b8ee2f3fa32f4e
|
||||
messages = ['invalid escape sequence',
|
||||
'Flags not at the start of the expression']
|
||||
with log.ignore_py_warnings(
|
||||
category=DeprecationWarning,
|
||||
message=r'({})'.format('|'.join(messages))):
|
||||
importlib.import_module(name)
|
||||
except ImportError as e:
|
||||
_die(text, e)
|
||||
|
||||
|
||||
def check_libraries():
|
||||
"""Check if all needed Python libraries are installed."""
|
||||
modules = {
|
||||
'pkg_resources':
|
||||
@ -262,32 +263,29 @@ def check_libraries(backend):
|
||||
'PyQt5.QtQml': _missing_str("PyQt5.QtQml"),
|
||||
'PyQt5.QtSql': _missing_str("PyQt5.QtSql"),
|
||||
}
|
||||
if backend == 'webengine':
|
||||
modules['PyQt5.QtWebEngineWidgets'] = _missing_str("QtWebEngine",
|
||||
webengine=True)
|
||||
modules['PyQt5.QtOpenGL'] = _missing_str("PyQt5.QtOpenGL")
|
||||
_check_modules(modules)
|
||||
|
||||
|
||||
def check_backend_libraries(backend):
|
||||
"""Make sure the libraries needed by the given backend are available.
|
||||
|
||||
Args:
|
||||
backend: The backend as usertypes.Backend member.
|
||||
"""
|
||||
from qutebrowser.utils import usertypes
|
||||
if backend == usertypes.Backend.QtWebEngine:
|
||||
modules = {
|
||||
'PyQt5.QtWebEngineWidgets':
|
||||
_missing_str("QtWebEngine", webengine=True),
|
||||
'PyQt5.QtOpenGL': _missing_str("PyQt5.QtOpenGL"),
|
||||
}
|
||||
else:
|
||||
assert backend == 'webkit'
|
||||
modules['PyQt5.QtWebKit'] = _missing_str("PyQt5.QtWebKit")
|
||||
modules['PyQt5.QtWebKitWidgets'] = _missing_str(
|
||||
"PyQt5.QtWebKitWidgets")
|
||||
|
||||
from qutebrowser.utils import log
|
||||
|
||||
for name, text in modules.items():
|
||||
try:
|
||||
# https://github.com/pallets/jinja/pull/628
|
||||
# https://bitbucket.org/birkenfeld/pygments-main/issues/1314/
|
||||
# https://github.com/pallets/jinja/issues/646
|
||||
# https://bitbucket.org/fdik/pypeg/commits/dd15ca462b532019c0a3be1d39b8ee2f3fa32f4e
|
||||
messages = ['invalid escape sequence',
|
||||
'Flags not at the start of the expression']
|
||||
with log.ignore_py_warnings(
|
||||
category=DeprecationWarning,
|
||||
message=r'({})'.format('|'.join(messages))):
|
||||
importlib.import_module(name)
|
||||
except ImportError as e:
|
||||
_die(text, e)
|
||||
assert backend == usertypes.Backend.QtWebKit, backend
|
||||
modules = {
|
||||
'PyQt5.QtWebKit': _missing_str("PyQt5.QtWebKit"),
|
||||
'PyQt5.QtWebKitWidgets': _missing_str("PyQt5.QtWebKitWidgets"),
|
||||
}
|
||||
_check_modules(modules)
|
||||
|
||||
|
||||
def remove_inputhook():
|
||||
@ -318,18 +316,7 @@ def check_optimize_flag():
|
||||
"unexpected behavior may occur.")
|
||||
|
||||
|
||||
def set_backend(backend):
|
||||
"""Set the objects.backend global to the given backend (as string)."""
|
||||
from qutebrowser.misc import objects
|
||||
from qutebrowser.utils import usertypes
|
||||
backends = {
|
||||
'webkit': usertypes.Backend.QtWebKit,
|
||||
'webengine': usertypes.Backend.QtWebEngine,
|
||||
}
|
||||
objects.backend = backends[backend]
|
||||
|
||||
|
||||
def earlyinit(args):
|
||||
def early_init(args):
|
||||
"""Do all needed early initialization.
|
||||
|
||||
Note that it's vital the other earlyinit functions get called in the right
|
||||
@ -348,10 +335,20 @@ def earlyinit(args):
|
||||
init_log(args)
|
||||
# Now we can be sure QtCore is available, so we can print dialogs on
|
||||
# errors, so people only using the GUI notice them as well.
|
||||
backend = get_backend(args)
|
||||
check_libraries(backend)
|
||||
check_libraries()
|
||||
check_qt_version()
|
||||
remove_inputhook()
|
||||
check_ssl_support(backend)
|
||||
check_ssl_support()
|
||||
check_optimize_flag()
|
||||
set_backend(backend)
|
||||
|
||||
|
||||
def init_with_backend(backend):
|
||||
"""Do later stages of init when we know the backend.
|
||||
|
||||
Args:
|
||||
backend: The backend as usertypes.Backend member.
|
||||
"""
|
||||
assert not isinstance(backend, str), backend
|
||||
assert backend is not None
|
||||
check_backend_libraries(backend)
|
||||
check_backend_ssl_support(backend)
|
||||
|
@ -167,7 +167,7 @@ def main():
|
||||
# from json.
|
||||
data = json.loads(args.json_args)
|
||||
args = argparse.Namespace(**data)
|
||||
earlyinit.earlyinit(args)
|
||||
earlyinit.early_init(args)
|
||||
# We do this imports late as earlyinit needs to be run first (because of
|
||||
# version checking and other early initialization)
|
||||
from qutebrowser import app
|
||||
|
@ -415,8 +415,9 @@ def fake_save_manager():
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fake_args():
|
||||
def fake_args(request):
|
||||
ns = types.SimpleNamespace()
|
||||
ns.backend = 'webengine' if request.config.webengine else 'webkit'
|
||||
objreg.register('args', ns)
|
||||
yield ns
|
||||
objreg.delete('args')
|
||||
|
@ -877,6 +877,9 @@ def init_patch(qapp, fake_save_manager, monkeypatch, config_tmpdir,
|
||||
monkeypatch.setattr(config, 'key_instance', None)
|
||||
monkeypatch.setattr(config, '_change_filters', [])
|
||||
monkeypatch.setattr(config, '_init_errors', [])
|
||||
# Make sure we get no SSL warning
|
||||
monkeypatch.setattr(config.earlyinit, 'check_backend_ssl_support',
|
||||
lambda _backend: None)
|
||||
yield
|
||||
try:
|
||||
objreg.delete('config-commands')
|
||||
@ -888,7 +891,7 @@ def init_patch(qapp, fake_save_manager, monkeypatch, config_tmpdir,
|
||||
@pytest.mark.parametrize('config_py', [True, 'error', False])
|
||||
@pytest.mark.parametrize('invalid_yaml', ['42', 'unknown', False])
|
||||
# pylint: disable=too-many-branches
|
||||
def test_early_init(init_patch, config_tmpdir, caplog,
|
||||
def test_early_init(init_patch, config_tmpdir, caplog, fake_args,
|
||||
load_autoconfig, config_py, invalid_yaml):
|
||||
# Prepare files
|
||||
autoconfig_file = config_tmpdir / 'autoconfig.yml'
|
||||
@ -914,7 +917,7 @@ def test_early_init(init_patch, config_tmpdir, caplog,
|
||||
'utf-8', ensure=True)
|
||||
|
||||
with caplog.at_level(logging.ERROR):
|
||||
config.early_init()
|
||||
config.early_init(fake_args)
|
||||
|
||||
# Check error messages
|
||||
expected_errors = []
|
||||
@ -954,15 +957,16 @@ def test_early_init(init_patch, config_tmpdir, caplog,
|
||||
assert config.instance._values == {'colors.hints.fg': 'magenta'}
|
||||
|
||||
|
||||
def test_early_init_invalid_change_filter(init_patch):
|
||||
def test_early_init_invalid_change_filter(init_patch, fake_args):
|
||||
config.change_filter('foobar')
|
||||
with pytest.raises(configexc.NoOptionError):
|
||||
config.early_init()
|
||||
config.early_init(fake_args)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('errors', [True, False])
|
||||
def test_late_init(init_patch, monkeypatch, fake_save_manager, mocker, errors):
|
||||
config.early_init()
|
||||
def test_late_init(init_patch, monkeypatch, fake_save_manager, fake_args,
|
||||
mocker, errors):
|
||||
config.early_init(fake_args)
|
||||
if errors:
|
||||
err = configexc.ConfigErrorDesc("Error text", Exception("Exception"))
|
||||
errs = configexc.ConfigFileErrors("config.py", [err])
|
||||
|
Loading…
Reference in New Issue
Block a user