Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55a88ceea6 | ||
|
|
d4bf04d2c8 | ||
|
|
cb527913dc | ||
|
|
ddfa82345c | ||
|
|
45c75d5e04 | ||
|
|
9404c61f10 | ||
|
|
01d2654c23 | ||
|
|
bad349aacf | ||
|
|
5dacf1431f | ||
|
|
27c46f20c0 | ||
|
|
97a14c14b3 | ||
|
|
0195f717c3 | ||
|
|
b3f395453b | ||
|
|
d411ec1eba | ||
|
|
db8fa5fdb6 | ||
|
|
2872ae5641 | ||
|
|
cbe0ff94a1 | ||
|
|
19a0a026dc | ||
|
|
2bf9a81451 | ||
|
|
35d5038ab1 | ||
|
|
bf1d6acb06 | ||
|
|
07b1b3fbd4 | ||
|
|
8539d092df | ||
|
|
dfe2f9e38c | ||
|
|
4f870f902c |
@@ -181,7 +181,10 @@ Active
|
||||
https://key.saka.io/[Saka Key]
|
||||
* Firefox addons (based on WebExtensions):
|
||||
https://addons.mozilla.org/en-GB/firefox/addon/vimium-ff/[Vimium-FF] (experimental),
|
||||
http://saka-key.lusakasa.com/[Saka Key]
|
||||
https://key.saka.io[Saka Key],
|
||||
https://github.com/cmcaine/tridactyl[Tridactyl] (in early development, working
|
||||
on a https://bugzilla.mozilla.org/show_bug.cgi?id=1215061[better API] for
|
||||
keyboard integration in Firefox).
|
||||
|
||||
Inactive
|
||||
~~~~~~~~
|
||||
|
||||
@@ -15,6 +15,34 @@ breaking changes (such as renamed commands) can happen in minor releases.
|
||||
// `Fixed` for any bug fixes.
|
||||
// `Security` to invite users to upgrade in case of vulnerabilities.
|
||||
|
||||
v1.0.2
|
||||
------
|
||||
|
||||
Fixes
|
||||
~~~~~
|
||||
|
||||
- Fix workaround for black screens or crashes with Nvidia cards
|
||||
- Handle a filesystem going read-only gracefully
|
||||
- Fix crash when setting `fonts.monospace`
|
||||
- Fix list options not being modifyable via `.append()` in `config.py`
|
||||
- Mark the content.notifications setting as QtWebKit only correctly
|
||||
- Fix wrong rendering of keys like `<back>` in the completion
|
||||
|
||||
Changed
|
||||
~~~~~~~
|
||||
|
||||
- Nicer error messages and other minor improvements
|
||||
|
||||
v1.0.1
|
||||
------
|
||||
|
||||
Fixes
|
||||
~~~~~
|
||||
|
||||
- Fixed starting after customizing `fonts.tabs` or `fonts.debug_console`.
|
||||
- Fixed starting with old PyQt versions compiled against newer Qt versions.
|
||||
- Fixed check for PyQt version to correctly enforce 5.7 (not 5.2).
|
||||
|
||||
v1.0.0
|
||||
------
|
||||
|
||||
|
||||
@@ -1738,6 +1738,8 @@ Valid values:
|
||||
|
||||
Default: +pass:[ask]+
|
||||
|
||||
This setting is only available with the QtWebKit backend.
|
||||
|
||||
[[content.pdfjs]]
|
||||
=== content.pdfjs
|
||||
Enable pdf.js to view PDF files in the browser.
|
||||
|
||||
@@ -54,4 +54,5 @@ qt_log_ignore =
|
||||
^Incompatible version of OpenSSL
|
||||
^QQuickWidget::invalidateRenderControl could not make context current
|
||||
^libpng warning: iCCP: known incorrect sRGB profile
|
||||
^inotify_add_watch(".*") failed: "No space left on device"
|
||||
xfail_strict = true
|
||||
|
||||
@@ -26,7 +26,7 @@ __copyright__ = "Copyright 2014-2017 Florian Bruhin (The Compiler)"
|
||||
__license__ = "GPL"
|
||||
__maintainer__ = __author__
|
||||
__email__ = "mail@qutebrowser.org"
|
||||
__version_info__ = (1, 0, 0)
|
||||
__version_info__ = (1, 0, 2)
|
||||
__version__ = '.'.join(str(e) for e in __version_info__)
|
||||
__description__ = "A keyboard-driven, vim-like browser based on PyQt5."
|
||||
|
||||
|
||||
@@ -28,8 +28,6 @@ Module attributes:
|
||||
"""
|
||||
|
||||
import os
|
||||
import ctypes
|
||||
import ctypes.util
|
||||
|
||||
from PyQt5.QtGui import QFont
|
||||
from PyQt5.QtWebEngineWidgets import (QWebEngineSettings, QWebEngineProfile,
|
||||
@@ -231,11 +229,6 @@ def init(args):
|
||||
if args.enable_webengine_inspector:
|
||||
os.environ['QTWEBENGINE_REMOTE_DEBUGGING'] = str(utils.random_port())
|
||||
|
||||
# WORKAROUND for
|
||||
# https://bugs.launchpad.net/ubuntu/+source/python-qt4/+bug/941826
|
||||
if utils.is_linux:
|
||||
ctypes.CDLL(ctypes.util.find_library("GL"), mode=ctypes.RTLD_GLOBAL)
|
||||
|
||||
_init_profiles()
|
||||
|
||||
# We need to do this here as a WORKAROUND for
|
||||
|
||||
@@ -202,7 +202,8 @@ class CompletionItemDelegate(QStyledItemDelegate):
|
||||
if index.column() in columns_to_filter and pattern:
|
||||
repl = r'<span class="highlight">\g<0></span>'
|
||||
text = re.sub(re.escape(pattern).replace(r'\ ', r'|'),
|
||||
repl, self._opt.text, flags=re.IGNORECASE)
|
||||
repl, html.escape(self._opt.text),
|
||||
flags=re.IGNORECASE)
|
||||
self._doc.setHtml(text)
|
||||
else:
|
||||
self._doc.setPlainText(self._opt.text)
|
||||
|
||||
@@ -75,6 +75,10 @@ class ConfigCommands:
|
||||
tabbed_browser.openurl(QUrl('qute://settings'), newtab=False)
|
||||
return
|
||||
|
||||
if option.endswith('!'):
|
||||
raise cmdexc.CommandError("Toggling values was moved to the "
|
||||
":config-cycle command")
|
||||
|
||||
if option.endswith('?') and option != '?':
|
||||
self._print_value(option[:-1])
|
||||
return
|
||||
|
||||
@@ -524,6 +524,7 @@ content.netrc_file:
|
||||
content.notifications:
|
||||
default: ask
|
||||
type: BoolAsk
|
||||
backend: QtWebKit
|
||||
desc: Allow websites to show notifications.
|
||||
|
||||
content.pdfjs:
|
||||
@@ -582,7 +583,7 @@ content.user_stylesheets:
|
||||
name: ListOrValue
|
||||
valtype: File
|
||||
none_ok: True
|
||||
default: null
|
||||
default: []
|
||||
desc: A list of user stylesheet filenames to use.
|
||||
|
||||
content.webgl:
|
||||
@@ -1333,7 +1334,7 @@ url.start_pages:
|
||||
type:
|
||||
name: ListOrValue
|
||||
valtype: FuzzyUrl
|
||||
default: "https://start.duckduckgo.com"
|
||||
default: ["https://start.duckduckgo.com"]
|
||||
desc: The page(s) to open at the start.
|
||||
|
||||
url.yank_ignored_parameters:
|
||||
|
||||
@@ -104,7 +104,9 @@ def _update_monospace_fonts():
|
||||
continue
|
||||
elif not isinstance(opt.typ, configtypes.Font):
|
||||
continue
|
||||
elif not config.instance.get_obj(name).endswith(' monospace'):
|
||||
|
||||
value = config.instance.get_obj(name)
|
||||
if value is None or not value.endswith(' monospace'):
|
||||
continue
|
||||
|
||||
config.instance.changed.emit(name)
|
||||
|
||||
@@ -1068,7 +1068,7 @@ class QtFont(Font):
|
||||
raise ValueError("Unexpected size unit in {!r}!".format(
|
||||
size)) # pragma: no cover
|
||||
|
||||
if family == 'monospace':
|
||||
if family == 'monospace' and self.monospace_fonts is not None:
|
||||
family = self.monospace_fonts
|
||||
# The Qt CSS parser handles " and ' before passing the string to
|
||||
# QFont.setFamily. We could do proper CSS-like parsing here, but since
|
||||
|
||||
@@ -44,3 +44,4 @@ rules:
|
||||
array-element-newline: "off"
|
||||
no-multi-spaces: ["error", {"ignoreEOLComments": true}]
|
||||
function-paren-newline: "off"
|
||||
multiline-comment-style: "off"
|
||||
|
||||
@@ -23,6 +23,8 @@ import os
|
||||
import sys
|
||||
import functools
|
||||
import html
|
||||
import ctypes
|
||||
import ctypes.util
|
||||
|
||||
import attr
|
||||
from PyQt5.QtCore import Qt
|
||||
@@ -31,7 +33,7 @@ from PyQt5.QtWidgets import (QApplication, QDialog, QPushButton, QHBoxLayout,
|
||||
from PyQt5.QtNetwork import QSslSocket
|
||||
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.utils import usertypes, objreg, version, qtutils, log
|
||||
from qutebrowser.utils import usertypes, objreg, version, qtutils, log, utils
|
||||
from qutebrowser.misc import objects, msgbox
|
||||
|
||||
|
||||
@@ -154,6 +156,19 @@ def _show_dialog(*args, **kwargs):
|
||||
sys.exit(usertypes.Exit.err_init)
|
||||
|
||||
|
||||
def _nvidia_shader_workaround():
|
||||
"""Work around QOpenGLShaderProgram issues.
|
||||
|
||||
NOTE: This needs to be called before _handle_nouveau_graphics, or some
|
||||
setups will segfault in version.opengl_vendor().
|
||||
|
||||
See https://bugs.launchpad.net/ubuntu/+source/python-qt4/+bug/941826
|
||||
"""
|
||||
assert objects.backend == usertypes.Backend.QtWebEngine, objects.backend
|
||||
if utils.is_linux:
|
||||
ctypes.CDLL(ctypes.util.find_library("GL"), mode=ctypes.RTLD_GLOBAL)
|
||||
|
||||
|
||||
def _handle_nouveau_graphics():
|
||||
assert objects.backend == usertypes.Backend.QtWebEngine, objects.backend
|
||||
|
||||
@@ -352,6 +367,7 @@ def init():
|
||||
if objects.backend == usertypes.Backend.QtWebEngine:
|
||||
_handle_ssl_support()
|
||||
_handle_wayland()
|
||||
_nvidia_shader_workaround()
|
||||
_handle_nouveau_graphics()
|
||||
else:
|
||||
assert objects.backend == usertypes.Backend.QtWebKit, objects.backend
|
||||
|
||||
@@ -32,7 +32,7 @@ import pkg_resources
|
||||
from PyQt5.QtCore import pyqtSlot, Qt, QSize
|
||||
from PyQt5.QtWidgets import (QDialog, QLabel, QTextEdit, QPushButton,
|
||||
QVBoxLayout, QHBoxLayout, QCheckBox,
|
||||
QDialogButtonBox, QApplication)
|
||||
QDialogButtonBox, QApplication, QMessageBox)
|
||||
|
||||
import qutebrowser
|
||||
from qutebrowser.utils import version, log, utils, objreg, usertypes
|
||||
@@ -511,10 +511,28 @@ class FatalCrashDialog(_CrashDialog):
|
||||
if self._chk_history.isChecked():
|
||||
try:
|
||||
history = objreg.get('web-history').get_recent()
|
||||
self._crash_info.append(("History", ''.join(history)))
|
||||
self._crash_info.append(("History",
|
||||
'\n'.join(str(e) for e in history)))
|
||||
except Exception:
|
||||
self._crash_info.append(("History", traceback.format_exc()))
|
||||
|
||||
@pyqtSlot()
|
||||
def on_report_clicked(self):
|
||||
"""Prevent empty reports."""
|
||||
if (not self._info.toPlainText().strip() and
|
||||
not self._contact.toPlainText().strip() and
|
||||
self._type == 'Segmentation fault' and
|
||||
self._func == 'qt_mainloop'):
|
||||
msgbox.msgbox(parent=self, title='Empty crash info',
|
||||
text="Empty reports for fatal crashes are useless "
|
||||
"and mean I'll spend time deleting reports I could "
|
||||
"spend on developing qutebrowser instead.\n\nPlease "
|
||||
"help making qutebrowser better by providing more "
|
||||
"information, or don't report this.",
|
||||
icon=QMessageBox.Critical)
|
||||
else:
|
||||
super().on_report_clicked()
|
||||
|
||||
|
||||
class ReportDialog(_CrashDialog):
|
||||
|
||||
|
||||
@@ -168,9 +168,11 @@ def qt_version(qversion=None, qt_version_str=None):
|
||||
|
||||
def check_qt_version():
|
||||
"""Check if the Qt version is recent enough."""
|
||||
from PyQt5.QtCore import PYQT_VERSION, PYQT_VERSION_STR
|
||||
from qutebrowser.utils import qtutils
|
||||
if not qtutils.version_check('5.7.1') or PYQT_VERSION < 0x050200:
|
||||
from PyQt5.QtCore import (qVersion, QT_VERSION, PYQT_VERSION,
|
||||
PYQT_VERSION_STR)
|
||||
from pkg_resources import parse_version
|
||||
if (QT_VERSION < 0x050701 or PYQT_VERSION < 0x050700 or
|
||||
parse_version(qVersion()) < parse_version('5.7.1')):
|
||||
text = ("Fatal error: Qt >= 5.7.1 and PyQt >= 5.7 are required, "
|
||||
"but Qt {} / PyQt {} is installed.".format(qt_version(),
|
||||
PYQT_VERSION_STR))
|
||||
|
||||
@@ -65,13 +65,12 @@ class SqliteError(SqlError):
|
||||
log.sql.debug("error code: {}".format(error.nativeErrorCode()))
|
||||
|
||||
# https://sqlite.org/rescode.html
|
||||
# https://github.com/qutebrowser/qutebrowser/issues/2930
|
||||
# https://github.com/qutebrowser/qutebrowser/issues/3004
|
||||
environmental_errors = [
|
||||
# SQLITE_LOCKED,
|
||||
# https://github.com/qutebrowser/qutebrowser/issues/2930
|
||||
'9',
|
||||
# SQLITE_FULL,
|
||||
# https://github.com/qutebrowser/qutebrowser/issues/3004
|
||||
'13',
|
||||
'8', # SQLITE_READONLY
|
||||
'9', # SQLITE_LOCKED,
|
||||
'13', # SQLITE_FULL,
|
||||
]
|
||||
self.environmental = error.nativeErrorCode() in environmental_errors
|
||||
|
||||
|
||||
@@ -33,7 +33,8 @@ import contextlib
|
||||
|
||||
import pkg_resources
|
||||
from PyQt5.QtCore import (qVersion, QEventLoop, QDataStream, QByteArray,
|
||||
QIODevice, QSaveFile, QT_VERSION_STR)
|
||||
QIODevice, QSaveFile, QT_VERSION_STR,
|
||||
PYQT_VERSION_STR)
|
||||
try:
|
||||
from PyQt5.QtWebKit import qWebKitVersion
|
||||
except ImportError: # pragma: no cover
|
||||
@@ -82,12 +83,18 @@ def version_check(version, exact=False, compiled=True):
|
||||
# Catch code using the old API for this
|
||||
assert exact not in [operator.gt, operator.lt, operator.ge, operator.le,
|
||||
operator.eq], exact
|
||||
if compiled and exact:
|
||||
raise ValueError("Can't use compiled=True with exact=True!")
|
||||
|
||||
parsed = pkg_resources.parse_version(version)
|
||||
op = operator.eq if exact else operator.ge
|
||||
result = op(pkg_resources.parse_version(qVersion()), parsed)
|
||||
if compiled and result:
|
||||
# v1 ==/>= parsed, now check if v2 ==/>= parsed too.
|
||||
# qVersion() ==/>= parsed, now check if QT_VERSION_STR ==/>= parsed.
|
||||
result = op(pkg_resources.parse_version(QT_VERSION_STR), parsed)
|
||||
if compiled and result:
|
||||
# FInally, check PYQT_VERSION_STR as well.
|
||||
result = op(pkg_resources.parse_version(PYQT_VERSION_STR), parsed)
|
||||
return result
|
||||
|
||||
|
||||
|
||||
@@ -882,7 +882,7 @@ def yaml_load(f):
|
||||
end = datetime.datetime.now()
|
||||
|
||||
delta = (end - start).total_seconds()
|
||||
deadline = 3 if 'CI' in os.environ else 1
|
||||
deadline = 3 if 'CI' in os.environ else 2
|
||||
if delta > deadline: # pragma: no cover
|
||||
log.misc.warning(
|
||||
"YAML load took unusually long, please report this at "
|
||||
|
||||
@@ -32,6 +32,8 @@ import pkg_resources
|
||||
import attr
|
||||
from PyQt5.QtCore import PYQT_VERSION_STR, QLibraryInfo
|
||||
from PyQt5.QtNetwork import QSslSocket
|
||||
from PyQt5.QtGui import (QOpenGLContext, QOpenGLVersionProfile,
|
||||
QOffscreenSurface)
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
|
||||
try:
|
||||
@@ -392,10 +394,6 @@ def opengl_vendor(): # pragma: no cover
|
||||
'Intel Open Source Technology Center'; or None if the vendor can't be
|
||||
determined.
|
||||
"""
|
||||
# We're doing those imports here because this is only available with Qt 5.4
|
||||
# or newer.
|
||||
from PyQt5.QtGui import (QOpenGLContext, QOpenGLVersionProfile,
|
||||
QOffscreenSurface)
|
||||
assert QApplication.instance()
|
||||
|
||||
old_context = QOpenGLContext.currentContext()
|
||||
|
||||
@@ -84,10 +84,11 @@ def _get_version_tag(tag):
|
||||
if package == 'qt':
|
||||
op = match.group('operator')
|
||||
do_skip = {
|
||||
'==': not qtutils.version_check(version, exact=True),
|
||||
'==': not qtutils.version_check(version, exact=True,
|
||||
compiled=False),
|
||||
'>=': not qtutils.version_check(version),
|
||||
'<': qtutils.version_check(version),
|
||||
'!=': qtutils.version_check(version, exact=True),
|
||||
'!=': qtutils.version_check(version, exact=True, compiled=False),
|
||||
}
|
||||
return pytest.mark.skipif(do_skip[op], reason='Needs ' + tag)
|
||||
elif package == 'pyqt':
|
||||
|
||||
@@ -51,6 +51,8 @@ Feature: Page history
|
||||
Then the history should contain:
|
||||
http://localhost:(port)/404 Error loading page: http://localhost:(port)/404
|
||||
|
||||
# Hangs a lot on AppVeyor
|
||||
@posix
|
||||
Scenario: History with invalid URL
|
||||
When I run :tab-only
|
||||
And I open data/javascript/window_open.html
|
||||
|
||||
@@ -133,9 +133,9 @@ class TestSet:
|
||||
"QtWebEngine backend!"):
|
||||
commands.set(0, 'content.cookies.accept', 'all')
|
||||
|
||||
@pytest.mark.parametrize('option', ['?', '!', 'url.auto_search'])
|
||||
@pytest.mark.parametrize('option', ['?', 'url.auto_search'])
|
||||
def test_empty(self, commands, option):
|
||||
"""Run ':set ?' / ':set !' / ':set url.auto_search'.
|
||||
"""Run ':set ?' / ':set url.auto_search'.
|
||||
|
||||
Should show an error.
|
||||
See https://github.com/qutebrowser/qutebrowser/issues/1109
|
||||
@@ -145,6 +145,16 @@ class TestSet:
|
||||
"value"):
|
||||
commands.set(win_id=0, option=option)
|
||||
|
||||
def test_toggle(self, commands):
|
||||
"""Try toggling a value.
|
||||
|
||||
Should show an nicer error.
|
||||
"""
|
||||
with pytest.raises(cmdexc.CommandError,
|
||||
match="Toggling values was moved to the "
|
||||
":config-cycle command"):
|
||||
commands.set(win_id=0, option='javascript.enabled!')
|
||||
|
||||
def test_invalid(self, commands):
|
||||
"""Run ':set foo?'.
|
||||
|
||||
|
||||
@@ -30,16 +30,28 @@ from qutebrowser.utils import usertypes
|
||||
|
||||
|
||||
def test_init(config_stub):
|
||||
"""Test reading the default yaml file and validating the values."""
|
||||
"""Test reading the default yaml file."""
|
||||
# configdata.init() is called by config_stub
|
||||
config_stub.val.aliases = {}
|
||||
assert isinstance(configdata.DATA, dict)
|
||||
assert 'ignore_case' in configdata.DATA
|
||||
|
||||
|
||||
def test_data(config_stub):
|
||||
"""Test various properties of the default values."""
|
||||
for option in configdata.DATA.values():
|
||||
# Make sure to_py and to_str work
|
||||
option.typ.to_py(option.default)
|
||||
option.typ.to_str(option.default)
|
||||
|
||||
# https://github.com/qutebrowser/qutebrowser/issues/3104
|
||||
# For lists/dicts, don't use None as default
|
||||
if isinstance(option.typ, (configtypes.Dict, configtypes.List)):
|
||||
assert option.default is not None
|
||||
# For ListOrValue, use a list as default
|
||||
if isinstance(option.typ, configtypes.ListOrValue):
|
||||
assert isinstance(option.default, list)
|
||||
|
||||
|
||||
# https://github.com/qutebrowser/qutebrowser/issues/2777
|
||||
@pytest.mark.no_ci
|
||||
|
||||
@@ -461,6 +461,20 @@ class TestConfigPy:
|
||||
assert config.instance._values['aliases']['foo'] == 'message-info foo'
|
||||
assert config.instance._values['aliases']['bar'] == 'message-info bar'
|
||||
|
||||
@pytest.mark.parametrize('option, value', [
|
||||
('content.user_stylesheets', 'style.css'),
|
||||
('url.start_pages', 'https://www.python.org/'),
|
||||
])
|
||||
def test_appending(self, config_tmpdir, confpy, option, value):
|
||||
"""Test appending an item to some special list types.
|
||||
|
||||
See https://github.com/qutebrowser/qutebrowser/issues/3104
|
||||
"""
|
||||
(config_tmpdir / 'style.css').ensure()
|
||||
confpy.write('c.{}.append("{}")'.format(option, value))
|
||||
confpy.read()
|
||||
assert config.instance._values[option][-1] == value
|
||||
|
||||
def test_oserror(self, tmpdir, data_tmpdir, config_tmpdir):
|
||||
with pytest.raises(configexc.ConfigFileErrors) as excinfo:
|
||||
configfiles.read_config_py(str(tmpdir / 'foo'))
|
||||
|
||||
@@ -27,7 +27,7 @@ import pytest
|
||||
|
||||
from qutebrowser import qutebrowser
|
||||
from qutebrowser.config import (config, configexc, configfiles, configinit,
|
||||
configdata)
|
||||
configdata, configtypes)
|
||||
from qutebrowser.utils import objreg, usertypes
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ def init_patch(qapp, fake_save_manager, monkeypatch, config_tmpdir,
|
||||
monkeypatch.setattr(config, 'key_instance', None)
|
||||
monkeypatch.setattr(config, 'change_filters', [])
|
||||
monkeypatch.setattr(configinit, '_init_errors', None)
|
||||
monkeypatch.setattr(configtypes.Font, 'monospace_fonts', None)
|
||||
yield
|
||||
try:
|
||||
objreg.delete('config-commands')
|
||||
@@ -200,18 +201,43 @@ class TestEarlyInit:
|
||||
assert msg.text == "set: NoOptionError - No option 'foo'"
|
||||
assert 'colors.completion.fg' not in config.instance._values
|
||||
|
||||
def test_monospace_fonts_init(self, init_patch, args):
|
||||
@pytest.mark.parametrize('settings, size, family', [
|
||||
# Only fonts.monospace customized
|
||||
([('fonts.monospace', '"Comic Sans MS"')], 8, 'Comic Sans MS'),
|
||||
# fonts.monospace and font settings customized
|
||||
# https://github.com/qutebrowser/qutebrowser/issues/3096
|
||||
([('fonts.monospace', '"Comic Sans MS"'),
|
||||
('fonts.tabs', '10pt monospace'),
|
||||
('fonts.keyhint', '10pt monospace')], 10, 'Comic Sans MS'),
|
||||
])
|
||||
@pytest.mark.parametrize('method', ['temp', 'auto', 'py'])
|
||||
def test_monospace_fonts_init(self, init_patch, args, config_tmpdir,
|
||||
method, settings, size, family):
|
||||
"""Ensure setting fonts.monospace at init works properly.
|
||||
|
||||
See https://github.com/qutebrowser/qutebrowser/issues/2973
|
||||
"""
|
||||
args.temp_settings = [('fonts.monospace', '"Comic Sans MS"')]
|
||||
if method == 'temp':
|
||||
args.temp_settings = settings
|
||||
elif method == 'auto':
|
||||
autoconfig_file = config_tmpdir / 'autoconfig.yml'
|
||||
lines = ["global:"] + [" {}: '{}'".format(k, v)
|
||||
for k, v in settings]
|
||||
autoconfig_file.write_text('\n'.join(lines), 'utf-8', ensure=True)
|
||||
elif method == 'py':
|
||||
config_py_file = config_tmpdir / 'config.py'
|
||||
lines = ["c.{} = '{}'".format(k, v) for k, v in settings]
|
||||
config_py_file.write_text('\n'.join(lines), 'utf-8', ensure=True)
|
||||
|
||||
configinit.early_init(args)
|
||||
|
||||
# Font
|
||||
assert config.instance.get('fonts.keyhint') == '8pt "Comic Sans MS"'
|
||||
expected = '{}pt "{}"'.format(size, family)
|
||||
assert config.instance.get('fonts.keyhint') == expected
|
||||
# QtFont
|
||||
assert config.instance.get('fonts.tabs').family() == 'Comic Sans MS'
|
||||
font = config.instance.get('fonts.tabs')
|
||||
assert font.pointSize() == size
|
||||
assert font.family() == family
|
||||
|
||||
def test_monospace_fonts_later(self, init_patch, args):
|
||||
"""Ensure setting fonts.monospace after init works properly.
|
||||
@@ -232,6 +258,15 @@ class TestEarlyInit:
|
||||
# Font subclass, but doesn't end with "monospace"
|
||||
assert 'fonts.web.family.standard' not in changed_options
|
||||
|
||||
def test_setting_monospace_fonts_family(self, init_patch, args):
|
||||
"""Make sure setting fonts.monospace after a family works.
|
||||
|
||||
See https://github.com/qutebrowser/qutebrowser/issues/3130
|
||||
"""
|
||||
configinit.early_init(args)
|
||||
config.instance.set_str('fonts.web.family.standard', '')
|
||||
config.instance.set_str('fonts.monospace', 'Terminus')
|
||||
|
||||
def test_force_software_rendering(self, monkeypatch, config_stub):
|
||||
"""Setting force_software_rendering should set the environment var."""
|
||||
envvar = 'QT_XCB_FORCE_SOFTWARE_OPENGL'
|
||||
|
||||
@@ -39,34 +39,36 @@ from qutebrowser.utils import qtutils, utils
|
||||
import overflow_test_cases
|
||||
|
||||
|
||||
@pytest.mark.parametrize('qversion, compiled, version, exact, expected', [
|
||||
@pytest.mark.parametrize(['qversion', 'compiled', 'pyqt', 'version', 'exact',
|
||||
'expected'], [
|
||||
# equal versions
|
||||
('5.4.0', None, '5.4.0', False, True),
|
||||
('5.4.0', None, '5.4.0', True, True), # exact=True
|
||||
('5.4.0', None, '5.4', True, True), # without trailing 0
|
||||
('5.4.0', None, None, '5.4.0', False, True),
|
||||
('5.4.0', None, None, '5.4.0', True, True), # exact=True
|
||||
('5.4.0', None, None, '5.4', True, True), # without trailing 0
|
||||
# newer version installed
|
||||
('5.4.1', None, '5.4', False, True),
|
||||
('5.4.1', None, '5.4', True, False), # exact=True
|
||||
('5.4.1', None, None, '5.4', False, True),
|
||||
('5.4.1', None, None, '5.4', True, False), # exact=True
|
||||
# older version installed
|
||||
('5.3.2', None, '5.4', False, False),
|
||||
('5.3.0', None, '5.3.2', False, False),
|
||||
('5.3.0', None, '5.3.2', True, False), # exact=True
|
||||
# strict
|
||||
('5.4.0', '5.3.0', '5.4.0', False, False),
|
||||
('5.4.0', '5.4.0', '5.4.0', False, True),
|
||||
# strict and exact=True
|
||||
('5.4.0', '5.5.0', '5.4.0', True, False),
|
||||
('5.5.0', '5.4.0', '5.4.0', True, False),
|
||||
('5.4.0', '5.4.0', '5.4.0', True, True),
|
||||
('5.3.2', None, None, '5.4', False, False),
|
||||
('5.3.0', None, None, '5.3.2', False, False),
|
||||
('5.3.0', None, None, '5.3.2', True, False), # exact=True
|
||||
# compiled=True
|
||||
# new Qt runtime, but compiled against older version
|
||||
('5.4.0', '5.3.0', '5.4.0', '5.4.0', False, False),
|
||||
# new Qt runtime, compiled against new version, but old PyQt
|
||||
('5.4.0', '5.4.0', '5.3.0', '5.4.0', False, False),
|
||||
# all up-to-date
|
||||
('5.4.0', '5.4.0', '5.4.0', '5.4.0', False, True),
|
||||
])
|
||||
def test_version_check(monkeypatch, qversion, compiled, version, exact,
|
||||
def test_version_check(monkeypatch, qversion, compiled, pyqt, version, exact,
|
||||
expected):
|
||||
"""Test for version_check().
|
||||
|
||||
Args:
|
||||
monkeypatch: The pytest monkeypatch fixture.
|
||||
qversion: The version to set as fake qVersion().
|
||||
compiled: The value for QT_VERSION_STR (set strict=True)
|
||||
compiled: The value for QT_VERSION_STR (set compiled=False)
|
||||
pyqt: The value for PYQT_VERSION_STR (set compiled=False)
|
||||
version: The version to compare with.
|
||||
exact: Use exact comparing (==)
|
||||
expected: The expected result.
|
||||
@@ -74,6 +76,7 @@ def test_version_check(monkeypatch, qversion, compiled, version, exact,
|
||||
monkeypatch.setattr(qtutils, 'qVersion', lambda: qversion)
|
||||
if compiled is not None:
|
||||
monkeypatch.setattr(qtutils, 'QT_VERSION_STR', compiled)
|
||||
monkeypatch.setattr(qtutils, 'PYQT_VERSION_STR', pyqt)
|
||||
compiled_arg = True
|
||||
else:
|
||||
compiled_arg = False
|
||||
@@ -82,6 +85,11 @@ def test_version_check(monkeypatch, qversion, compiled, version, exact,
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_version_check_compiled_and_exact():
|
||||
with pytest.raises(ValueError):
|
||||
qtutils.version_check('1.2.3', exact=True, compiled=True)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('version, is_new', [
|
||||
('537.21', False), # QtWebKit 5.1
|
||||
('538.1', False), # Qt 5.8
|
||||
|
||||
Reference in New Issue
Block a user