Compare commits

..

25 Commits

Author SHA1 Message Date
Florian Bruhin
55a88ceea6 Release v1.0.2 2017-10-17 07:44:14 +02:00
Florian Bruhin
d4bf04d2c8 Bump up yaml timeout a bit
(cherry picked from commit 1a7612e559)
2017-10-17 06:29:00 +02:00
Florian Bruhin
cb527913dc Show better error message when trying to toggle with :set
(cherry picked from commit d8384ced0a)
2017-10-17 06:27:07 +02:00
Florian Bruhin
ddfa82345c Fix HTML escaping in completion
(cherry picked from commit e766fe14fc)
2017-10-16 12:27:45 +02:00
Florian Bruhin
45c75d5e04 Fix setting monospace fonts with None values
Fixes #3130

(cherry picked from commit 2a65cadb67)
2017-10-16 06:18:29 +02:00
Florian Bruhin
9404c61f10 Add SQLITE_READONLY to environmental errors
(cherry picked from commit fa4a66f7b3)
2017-10-15 21:10:31 +02:00
Florian Bruhin
01d2654c23 Improve history formatting in crashdialog 2017-10-14 22:27:30 +02:00
Florian Bruhin
bad349aacf Fix getting history in crash dialog 2017-10-14 22:23:03 +02:00
Florian Bruhin
5dacf1431f eslint: Disable multiline-comment-style 2017-10-14 21:41:56 +02:00
Florian Bruhin
27c46f20c0 Make sure the config default values are mutable
While the old values meant the same thing, they weren't mutable, so the config
couldn't modify them with a simple .append().

Fixes #3104
2017-10-14 16:40:44 +02:00
Florian Bruhin
97a14c14b3 Update changelog
[ci skip]
2017-10-14 12:50:34 +02:00
Florian Bruhin
0195f717c3 Move QOpenGL imports to the top
We don't support Qt < 5.4 anymore anyways.
2017-10-14 12:11:41 +02:00
Florian Bruhin
b3f395453b Run Nvidia shader workaround earlier
We need to do it before utils.opengl_vendor(), and it fits better there anyway.
This was a regression in v1.0.

See #2554, #3106
2017-10-14 12:10:21 +02:00
Florian Bruhin
d411ec1eba Mark content.notifications as QtWebKit-only 2017-10-13 23:18:36 +02:00
Florian Bruhin
db8fa5fdb6 Skip "History with invalid URL" test on Windows
For some reason, this hangs a lot on AppVeyor
2017-10-13 10:45:40 +02:00
Florian Bruhin
2872ae5641 Release v1.0.1 2017-10-13 09:21:56 +02:00
Florian Bruhin
cbe0ff94a1 Ignore inotify_add_watch Qt warning
This happens on Travis from time to time.
2017-10-13 09:12:31 +02:00
Florian Bruhin
19a0a026dc Update Firefox extension list in README
[ci skip]
2017-10-13 08:07:32 +02:00
Florian Bruhin
2bf9a81451 Prevent empty segfault reports 2017-10-13 07:52:55 +02:00
Florian Bruhin
35d5038ab1 Add missing test 2017-10-12 22:42:58 +02:00
Florian Bruhin
bf1d6acb06 Properly fix up version checks... 2017-10-12 22:41:52 +02:00
Florian Bruhin
07b1b3fbd4 Update changelog
[ci skip]
2017-10-12 19:59:46 +02:00
Florian Bruhin
8539d092df Fix version checking in earlyinit
With the previous commit, we also checked that PyQt was >= 5.7.1, but we want to
support PyQt 5.7.0. Instead, we now check the individual components by hand.

Also, the previous check accidentally allowed PyQt >= 5.2.0 instead of 5.7.0.
2017-10-12 19:41:49 +02:00
Florian Bruhin
dfe2f9e38c Also check PyQt version for qtutils.version_check()
With an older PyQt built against a newer Qt, we still don't have its features
available.

This also drops support for exact=True with compiled=True as the semantics for
that are unclear, and it's not used.
2017-10-12 19:13:20 +02:00
Florian Bruhin
4f870f902c Fix loading of monospace fonts in configtypes.QtFont
See #3096
2017-10-12 18:26:54 +02:00
26 changed files with 219 additions and 61 deletions

View File

@@ -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
~~~~~~~~

View File

@@ -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
------

View File

@@ -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.

View File

@@ -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

View File

@@ -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."

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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:

View File

@@ -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)

View File

@@ -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

View File

@@ -44,3 +44,4 @@ rules:
array-element-newline: "off"
no-multi-spaces: ["error", {"ignoreEOLComments": true}]
function-paren-newline: "off"
multiline-comment-style: "off"

View File

@@ -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

View File

@@ -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):

View File

@@ -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))

View File

@@ -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

View File

@@ -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

View File

@@ -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 "

View File

@@ -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()

View File

@@ -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':

View File

@@ -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

View File

@@ -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?'.

View File

@@ -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

View File

@@ -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'))

View File

@@ -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'

View File

@@ -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