summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/bleeding.yml2
-rw-r--r--doc/changelog.asciidoc7
-rw-r--r--doc/help/commands.asciidoc1
-rw-r--r--misc/requirements/requirements-check-manifest.txt4
-rw-r--r--misc/requirements/requirements-dev.txt8
-rw-r--r--misc/requirements/requirements-flake8.txt2
-rw-r--r--misc/requirements/requirements-mypy.txt10
-rw-r--r--misc/requirements/requirements-pyinstaller.txt2
-rw-r--r--misc/requirements/requirements-pylint.txt4
-rw-r--r--misc/requirements/requirements-sphinx.txt12
-rw-r--r--misc/requirements/requirements-tests.txt20
-rw-r--r--misc/requirements/requirements-tox.txt14
-rwxr-xr-xmisc/userscripts/password_fill6
-rw-r--r--qutebrowser/browser/commands.py22
-rw-r--r--qutebrowser/utils/version.py2
-rw-r--r--requirements.txt6
-rw-r--r--scripts/dev/recompile_requirements.py4
-rw-r--r--tests/conftest.py70
-rw-r--r--tests/end2end/conftest.py2
-rw-r--r--tests/end2end/features/tabs.feature21
-rw-r--r--tests/unit/utils/test_urlmatch.py157
-rw-r--r--tests/unit/utils/test_version.py21
-rw-r--r--tox.ini2
23 files changed, 285 insertions, 114 deletions
diff --git a/.github/workflows/bleeding.yml b/.github/workflows/bleeding.yml
index 766f535d7..0d2c4f1ef 100644
--- a/.github/workflows/bleeding.yml
+++ b/.github/workflows/bleeding.yml
@@ -58,7 +58,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
- python-version: 3.9
+ python-version: 3.10
- name: Get asciidoc
uses: actions/checkout@v2
with:
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index f86b84622..7abaffcad 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -24,6 +24,13 @@ Changed
- Improved message if a spawned process wasn't found and a Flatpak container is
in use.
+- The `:tab-move` command now takes `start` and `end` as `index` to move a tab
+ to the first/last position.
+- Tests now automatically pick the backend (QtWebKit/QtWebEngine) based on
+ what's available. The `QUTE_BDD_WEBENGINE` environment variable and
+ `--qute-bdd-webengine` argument got replaced by `QUTE_TESTS_BACKEND` and
+ `--qute-backend` respectively, which can be set to either `webengine` or
+ `webkit`.
[[v2.4.1]]
v2.4.1 (unreleased)
diff --git a/doc/help/commands.asciidoc b/doc/help/commands.asciidoc
index 8c11e15cc..442c136a7 100644
--- a/doc/help/commands.asciidoc
+++ b/doc/help/commands.asciidoc
@@ -1431,6 +1431,7 @@ If neither is given, move it to the first position.
==== positional arguments
* +'index'+: `+` or `-` to move relative to the current tab by count, or a default of 1 space.
A tab index to move to that index.
+ `start` and `end` to move to the start and the end.
==== count
diff --git a/misc/requirements/requirements-check-manifest.txt b/misc/requirements/requirements-check-manifest.txt
index 21843c4ae..c61218ba3 100644
--- a/misc/requirements/requirements-check-manifest.txt
+++ b/misc/requirements/requirements-check-manifest.txt
@@ -2,8 +2,8 @@
build==0.7.0
check-manifest==0.47
-packaging==21.2
+packaging==21.3
pep517==0.12.0
-pyparsing==2.4.7
+pyparsing==3.0.6
toml==0.10.2
tomli==1.2.2
diff --git a/misc/requirements/requirements-dev.txt b/misc/requirements/requirements-dev.txt
index 088604a77..e8b333aa4 100644
--- a/misc/requirements/requirements-dev.txt
+++ b/misc/requirements/requirements-dev.txt
@@ -4,17 +4,17 @@ bump2version==1.0.1
certifi==2021.10.8
cffi==1.15.0
charset-normalizer==2.0.7
-cryptography==35.0.0
+cryptography==36.0.0
Deprecated==1.2.13
github3.py==3.0.0
hunter==3.3.8
idna==3.3
jwcrypto==1.0
manhole==1.8.0
-packaging==21.2
-pycparser==2.20
+packaging==21.3
+pycparser==2.21
Pympler==0.9
-pyparsing==2.4.7
+pyparsing==3.0.6
PyQt-builder==1.12.2
python-dateutil==2.8.2
requests==2.26.0
diff --git a/misc/requirements/requirements-flake8.txt b/misc/requirements/requirements-flake8.txt
index 08b75e2bf..551536629 100644
--- a/misc/requirements/requirements-flake8.txt
+++ b/misc/requirements/requirements-flake8.txt
@@ -21,4 +21,4 @@ pycodestyle==2.8.0
pydocstyle==6.1.1
pyflakes==2.4.0
six==1.16.0
-snowballstemmer==2.1.0
+snowballstemmer==2.2.0
diff --git a/misc/requirements/requirements-mypy.txt b/misc/requirements/requirements-mypy.txt
index 5aa36d659..ce64972b3 100644
--- a/misc/requirements/requirements-mypy.txt
+++ b/misc/requirements/requirements-mypy.txt
@@ -2,12 +2,12 @@
chardet==4.0.0
diff-cover==6.4.2
-importlib-metadata==4.8.1
+importlib-metadata==4.8.2
importlib-resources==5.4.0
inflect==5.3.0
-Jinja2==3.0.2
+Jinja2==3.0.3
jinja2-pluralize==0.3.0
-lxml==4.6.3
+lxml==4.6.4
MarkupSafe==2.0.1
mypy==0.910
mypy-extensions==0.4.3
@@ -16,6 +16,6 @@ Pygments==2.10.0
PyQt5-stubs==5.15.2.0
toml==0.10.2
types-dataclasses==0.6.1
-types-PyYAML==6.0.0
-typing-extensions==3.10.0.2
+types-PyYAML==6.0.1
+typing_extensions==4.0.0
zipp==3.6.0
diff --git a/misc/requirements/requirements-pyinstaller.txt b/misc/requirements/requirements-pyinstaller.txt
index 8d5567e67..9a53c11cd 100644
--- a/misc/requirements/requirements-pyinstaller.txt
+++ b/misc/requirements/requirements-pyinstaller.txt
@@ -1,5 +1,5 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
altgraph==0.17.2
-pyinstaller==4.6
+pyinstaller==4.7
pyinstaller-hooks-contrib==2021.3
diff --git a/misc/requirements/requirements-pylint.txt b/misc/requirements/requirements-pylint.txt
index abc6c2812..5b91165f5 100644
--- a/misc/requirements/requirements-pylint.txt
+++ b/misc/requirements/requirements-pylint.txt
@@ -4,7 +4,7 @@ astroid==2.3.3 # rq.filter: < 2.4
certifi==2021.10.8
cffi==1.15.0
charset-normalizer==2.0.7
-cryptography==35.0.0
+cryptography==36.0.0
Deprecated==1.2.13
future==0.18.2
github3.py==3.0.0
@@ -14,7 +14,7 @@ jwcrypto==1.0
lazy-object-proxy==1.4.3
mccabe==0.6.1
pefile==2021.9.3
-pycparser==2.20
+pycparser==2.21
pylint==2.4.4 # rq.filter: < 2.5
python-dateutil==2.8.2
./scripts/dev/pylint_checkers
diff --git a/misc/requirements/requirements-sphinx.txt b/misc/requirements/requirements-sphinx.txt
index 86553bb4c..b131f721f 100644
--- a/misc/requirements/requirements-sphinx.txt
+++ b/misc/requirements/requirements-sphinx.txt
@@ -6,16 +6,16 @@ certifi==2021.10.8
charset-normalizer==2.0.7
docutils==0.17.1
idna==3.3
-imagesize==1.2.0
-Jinja2==3.0.2
+imagesize==1.3.0
+Jinja2==3.0.3
MarkupSafe==2.0.1
-packaging==21.2
+packaging==21.3
Pygments==2.10.0
-pyparsing==2.4.7
+pyparsing==3.0.6
pytz==2021.3
requests==2.26.0
-snowballstemmer==2.1.0
-Sphinx==4.2.0
+snowballstemmer==2.2.0
+Sphinx==4.3.0
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
diff --git a/misc/requirements/requirements-tests.txt b/misc/requirements/requirements-tests.txt
index 23fb69402..8b518c6c2 100644
--- a/misc/requirements/requirements-tests.txt
+++ b/misc/requirements/requirements-tests.txt
@@ -6,33 +6,33 @@ certifi==2021.10.8
charset-normalizer==2.0.7
cheroot==8.5.2
click==8.0.3
-coverage==6.1.1
+coverage==6.1.2
EasyProcess==0.3
execnet==1.9.0
-filelock==3.3.2
+filelock==3.4.0
Flask==2.0.2
glob2==0.7
hunter==3.3.8
-hypothesis==6.24.1
+hypothesis==6.27.0
icdiff==2.0.4
idna==3.3
iniconfig==1.1.1
itsdangerous==2.0.1
jaraco.functools==3.4.0
-# Jinja2==3.0.2
-Mako==1.1.5
+# Jinja2==3.0.3
+Mako==1.1.6
manhole==1.8.0
# MarkupSafe==2.0.1
-more-itertools==8.10.0
-packaging==21.2
+more-itertools==8.11.0
+packaging==21.3
parse==1.19.0
parse-type==0.5.2
pluggy==1.0.0
pprintpp==0.4.0
-py==1.10.0
+py==1.11.0
py-cpuinfo==8.0.0
Pygments==2.10.0
-pyparsing==2.4.7
+pyparsing==3.0.6
pytest==6.2.5
pytest-bdd==4.1.0
pytest-benchmark==3.4.1
@@ -51,7 +51,7 @@ requests==2.26.0
requests-file==1.5.1
six==1.16.0
sortedcontainers==2.4.0
-soupsieve==2.2.1
+soupsieve==2.3.1
tldextract==3.1.2
toml==0.10.2
tomli==1.2.2
diff --git a/misc/requirements/requirements-tox.txt b/misc/requirements/requirements-tox.txt
index 248c850c2..630925db5 100644
--- a/misc/requirements/requirements-tox.txt
+++ b/misc/requirements/requirements-tox.txt
@@ -1,17 +1,17 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
-backports.entry-points-selectable==1.1.0
+backports.entry-points-selectable==1.1.1
distlib==0.3.3
-filelock==3.3.2
-packaging==21.2
+filelock==3.4.0
+packaging==21.3
pip==21.3.1
platformdirs==2.4.0
pluggy==1.0.0
-py==1.10.0
-pyparsing==2.4.7
-setuptools==58.4.0
+py==1.11.0
+pyparsing==3.0.6
+setuptools==59.2.0
six==1.16.0
toml==0.10.2
tox==3.24.4
-virtualenv==20.9.0
+virtualenv==20.10.0
wheel==0.37.0
diff --git a/misc/userscripts/password_fill b/misc/userscripts/password_fill
index c46253d41..3ea8fd9f6 100755
--- a/misc/userscripts/password_fill
+++ b/misc/userscripts/password_fill
@@ -241,7 +241,7 @@ pass_backend() {
if $GPG "${GPG_OPTS[@]}" -d "$passfile" \
| grep --max-count=1 -iE "${match_line_pattern}${url}" > /dev/null
then
- passfile="${passfile#$PREFIX}"
+ passfile="${passfile#"$PREFIX"}"
passfile="${passfile#/}"
files+=( "${passfile%.gpg}" )
fi
@@ -250,7 +250,7 @@ pass_backend() {
if ((match_filename)) ; then
# add entries with matching filepath
while read -r passfile ; do
- passfile="${passfile#$PREFIX}"
+ passfile="${passfile#"$PREFIX"}"
passfile="${passfile#/}"
files+=( "${passfile%.gpg}" )
done < <(find -L "$PREFIX" -iname '*.gpg' | grep "$url")
@@ -267,7 +267,7 @@ pass_backend() {
else
if [[ $line =~ $user_pattern ]] ; then
# remove the matching prefix "user: " from the beginning of the line
- username=${line#${BASH_REMATCH[0]}}
+ username=${line#"${BASH_REMATCH[0]}"}
break
fi
fi
diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py
index 5937e7604..796bb2eb3 100644
--- a/qutebrowser/browser/commands.py
+++ b/qutebrowser/browser/commands.py
@@ -1005,11 +1005,10 @@ class CommandDispatcher:
raise cmdutils.CommandError("There's no tab with index {}!".format(
index))
- @cmdutils.register(instance='command-dispatcher', scope='window')
- @cmdutils.argument('index', choices=['+', '-'])
- @cmdutils.argument('count', value=cmdutils.Value.count)
- def tab_move(self, index: Union[str, int] = None,
- count: int = None) -> None:
+ @cmdutils.register(instance="command-dispatcher", scope="window")
+ @cmdutils.argument("index", choices=["+", "-", "start", "end"])
+ @cmdutils.argument("count", value=cmdutils.Value.count)
+ def tab_move(self, index: Union[str, int] = None, count: int = None) -> None:
"""Move the current tab according to the argument and [count].
If neither is given, move it to the first position.
@@ -1018,24 +1017,29 @@ class CommandDispatcher:
index: `+` or `-` to move relative to the current tab by
count, or a default of 1 space.
A tab index to move to that index.
+ `start` and `end` to move to the start and the end.
count: If moving relatively: Offset.
If moving absolutely: New position (default: 0). This
overrides the index argument, if given.
"""
- if index in ['+', '-']:
+ if index in ["+", "-"]:
# relative moving
new_idx = self._current_index()
delta = 1 if count is None else count
- if index == '-':
+ if index == "-":
new_idx -= delta
- elif index == '+': # pragma: no branch
+ elif index == "+": # pragma: no branch
new_idx += delta
if config.val.tabs.wrap:
new_idx %= self._count()
else:
# absolute moving
- if count is not None:
+ if index == "start":
+ new_idx = 0
+ elif index == "end":
+ new_idx = self._count() - 1
+ elif count is not None:
new_idx = count - 1
elif index is not None:
assert isinstance(index, int)
diff --git a/qutebrowser/utils/version.py b/qutebrowser/utils/version.py
index 8cd244fca..3beb6fb83 100644
--- a/qutebrowser/utils/version.py
+++ b/qutebrowser/utils/version.py
@@ -773,8 +773,6 @@ def _backend() -> str:
if objects.backend == usertypes.Backend.QtWebKit:
return 'new QtWebKit (WebKit {})'.format(qWebKitVersion())
elif objects.backend == usertypes.Backend.QtWebEngine:
- webengine = usertypes.Backend.QtWebEngine
- assert objects.backend == webengine, objects.backend
return str(qtwebengine_versions(
avoid_init='avoid-chromium-init' in objects.debug_flags))
raise utils.Unreachable(objects.backend)
diff --git a/requirements.txt b/requirements.txt
index 0805ad6cc..e088ca805 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,11 +3,11 @@
adblock==0.5.0
colorama==0.4.4
dataclasses==0.6 ; python_version<"3.7"
-importlib-metadata==4.8.1 ; python_version<"3.8"
+importlib-metadata==4.8.2 ; python_version<"3.8"
importlib-resources==5.4.0 ; python_version<"3.9"
-Jinja2==3.0.2
+Jinja2==3.0.3
MarkupSafe==2.0.1
Pygments==2.10.0
PyYAML==6.0
-typing-extensions==3.10.0.2
+typing_extensions==4.0.0 ; python_version<"3.8"
zipp==3.6.0
diff --git a/scripts/dev/recompile_requirements.py b/scripts/dev/recompile_requirements.py
index c013346ae..23878e73f 100644
--- a/scripts/dev/recompile_requirements.py
+++ b/scripts/dev/recompile_requirements.py
@@ -133,7 +133,7 @@ CHANGELOG_URLS = {
'six': 'https://github.com/benjaminp/six/blob/master/CHANGES',
'altgraph': 'https://github.com/ronaldoussoren/altgraph/blob/master/doc/changelog.rst',
'urllib3': 'https://github.com/urllib3/urllib3/blob/master/CHANGES.rst',
- 'lxml': 'https://lxml.de/index.html#old-versions',
+ 'lxml': 'https://github.com/lxml/lxml/blob/master/CHANGES.txt',
'jwcrypto': 'https://github.com/latchset/jwcrypto/commits/master',
'wrapt': 'https://github.com/GrahamDumpleton/wrapt/blob/develop/docs/changes.rst',
'pep517': 'https://github.com/pypa/pep517/blob/master/doc/changelog.rst',
@@ -159,7 +159,7 @@ CHANGELOG_URLS = {
'idna': 'https://github.com/kjd/idna/blob/master/HISTORY.rst',
'tldextract': 'https://github.com/john-kurkowski/tldextract/blob/master/CHANGELOG.md',
'backports.entry-points-selectable': 'https://github.com/jaraco/backports.entry_points_selectable/blob/main/CHANGES.rst',
- 'typing-extensions': 'https://github.com/python/typing/commits/master/typing_extensions',
+ 'typing_extensions': 'https://github.com/python/typing/commits/master/typing_extensions',
'diff-cover': 'https://github.com/Bachmann1234/diff_cover/blob/master/CHANGELOG',
'pytest-icdiff': 'https://github.com/hjwp/pytest-icdiff/blob/master/HISTORY.rst',
'icdiff': 'https://github.com/jeffkaufman/icdiff/blob/master/ChangeLog',
diff --git a/tests/conftest.py b/tests/conftest.py
index 40631af34..26cc04345 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -214,20 +214,74 @@ def pytest_addoption(parser):
help="Delay between qutebrowser commands.")
parser.addoption('--qute-profile-subprocs', action='store_true',
default=False, help="Run cProfile for subprocesses.")
- parser.addoption('--qute-bdd-webengine', action='store_true',
- help='Use QtWebEngine for BDD tests')
+ parser.addoption('--qute-backend', action='store',
+ choices=['webkit', 'webengine'], help='Set backend for BDD tests')
def pytest_configure(config):
- webengine_arg = config.getoption('--qute-bdd-webengine')
- webengine_env = os.environ.get('QUTE_BDD_WEBENGINE', 'false')
- config.webengine = webengine_arg or webengine_env == 'true'
- # Fail early if QtWebEngine is not available
- if config.webengine:
- import PyQt5.QtWebEngineWidgets
+ backend = _select_backend(config)
+ config.webengine = backend == 'webengine'
+
earlyinit.configure_pyqt()
+def _select_backend(config):
+ """Select the backend for running tests.
+
+ The backend is auto-selected in the following manner:
+ 1. Use QtWebKit if available
+ 2. Otherwise use QtWebEngine as a fallback
+
+ Auto-selection is overridden by either passing a backend via
+ `--qute-backend=<backend>` or setting the environment variable
+ `QUTE_TESTS_BACKEND=<backend>`.
+
+ Args:
+ config: pytest config
+
+ Raises:
+ ImportError if the selected backend is not available.
+
+ Returns:
+ The selected backend as a string (e.g. 'webkit').
+ """
+ backend_arg = config.getoption('--qute-backend')
+ backend_env = os.environ.get('QUTE_TESTS_BACKEND')
+
+ backend = backend_arg or backend_env or _auto_select_backend()
+
+ # Fail early if selected backend is not available
+ if backend == 'webkit':
+ import PyQt5.QtWebKitWidgets
+ elif backend == 'webengine':
+ import PyQt5.QtWebEngineWidgets
+ else:
+ raise utils.Unreachable(backend)
+
+ return backend
+
+
+def _auto_select_backend():
+ try:
+ # Try to use QtWebKit as the default backend
+ import PyQt5.QtWebKitWidgets
+ return 'webkit'
+ except ImportError:
+ # Try to use QtWebEngine as a fallback and fail early
+ # if that's also not available
+ import PyQt5.QtWebEngineWidgets
+ return 'webengine'
+
+
+def pytest_report_header(config):
+ if config.webengine:
+ backend_version = version.qtwebengine_versions(avoid_init=True)
+ else:
+ backend_version = version.qWebKitVersion()
+
+ return f'backend: {backend_version}'
+
+
@pytest.fixture(scope='session', autouse=True)
def check_display(request):
if utils.is_linux and not os.environ.get('DISPLAY', ''):
diff --git a/tests/end2end/conftest.py b/tests/end2end/conftest.py
index a4a089cea..16170d460 100644
--- a/tests/end2end/conftest.py
+++ b/tests/end2end/conftest.py
@@ -165,7 +165,7 @@ if not getattr(sys, 'frozen', False):
def pytest_collection_modifyitems(config, items):
- """Apply @qtwebengine_* markers; skip unittests with QUTE_BDD_WEBENGINE."""
+ """Apply @qtwebengine_* markers."""
# WORKAROUND for https://bugreports.qt.io/browse/QTBUG-75884
# (note this isn't actually fixed properly before Qt 5.15)
header_bug_fixed = qtutils.version_check('5.15', compiled=False)
diff --git a/tests/end2end/features/tabs.feature b/tests/end2end/features/tabs.feature
index ab6098a3e..3715d5765 100644
--- a/tests/end2end/features/tabs.feature
+++ b/tests/end2end/features/tabs.feature
@@ -633,6 +633,27 @@ Feature: Tab management
- data/numbers/1.txt (active)
- data/numbers/3.txt
+ Scenario: :tab-move with absolute position
+ When I open data/numbers/1.txt
+ And I open data/numbers/2.txt in a new tab
+ And I open data/numbers/3.txt in a new tab
+ And I run :tab-focus 1
+ And I run :tab-move end
+ Then the following tabs should be open:
+ - data/numbers/2.txt
+ - data/numbers/3.txt
+ - data/numbers/1.txt (active)
+
+ Scenario: :tab-move with absolute position
+ When I open data/numbers/1.txt
+ And I open data/numbers/2.txt in a new tab
+ And I open data/numbers/3.txt in a new tab
+ And I run :tab-move start
+ Then the following tabs should be open:
+ - data/numbers/3.txt (active)
+ - data/numbers/1.txt
+ - data/numbers/2.txt
+
Scenario: Make sure :tab-move retains metadata
When I open data/title.html
And I open data/hello.txt in a new tab
diff --git a/tests/unit/utils/test_urlmatch.py b/tests/unit/utils/test_urlmatch.py
index 35ccc94fe..caf52c76d 100644
--- a/tests/unit/utils/test_urlmatch.py
+++ b/tests/unit/utils/test_urlmatch.py
@@ -37,24 +37,30 @@ from PyQt5.QtCore import QUrl
from qutebrowser.utils import urlmatch
+# pylint: disable=line-too-long
+
@pytest.mark.parametrize('pattern, error', [
### Chromium: kMissingSchemeSeparator
## TEST(ExtensionURLPatternTest, ParseInvalid)
# ("http", "No scheme given"),
- ("http:", "Invalid port: Port is empty"),
- ("http:/", "Invalid port: Port is empty"),
- ("about://", "Pattern without path"),
- ("http:/bar", "Invalid port: Port is empty"),
+ pytest.param("http:", "Invalid port: Port is empty", id='scheme-no-slash'),
+ pytest.param("http:/", "Invalid port: Port is empty", id='scheme-single-slash'),
+ pytest.param("about://", "Pattern without path", id='scheme-no-path'),
+ pytest.param(
+ "http:/bar",
+ "Invalid port: Port is empty",
+ id='scheme-single-slash-path',
+ ),
### Chromium: kEmptyHost
## TEST(ExtensionURLPatternTest, ParseInvalid)
- ("http://", "Pattern without host"),
- ("http:///", "Pattern without host"),
- ("http://:1234/", "Pattern without host"),
- ("http://*./", "Pattern without host"),
+ pytest.param("http://", "Pattern without host", id='host-double-slash'),
+ pytest.param("http:///", "Pattern without host", id='host-triple-slash'),
+ pytest.param("http://:1234/", "Pattern without host", id='host-port'),
+ pytest.param("http://*./", "Pattern without host", id='host-pattern'),
## TEST(ExtensionURLPatternTest, IPv6Patterns)
- ("http://[]:8888/*", "Pattern without host"),
+ pytest.param("http://[]:8888/*", "Pattern without host", id='host-ipv6'),
### Chromium: kEmptyPath
## TEST(ExtensionURLPatternTest, ParseInvalid)
@@ -63,53 +69,132 @@ from qutebrowser.utils import urlmatch
### Chromium: kInvalidHost
## TEST(ExtensionURLPatternTest, ParseInvalid)
- ("http://\0www/", "May not contain NUL byte"),
+ pytest.param("http://\0www/", "May not contain NUL byte", id='host-nul'),
## TEST(ExtensionURLPatternTest, IPv6Patterns)
# No closing bracket (`]`).
- ("http://[2607:f8b0:4005:805::200e/*", "Invalid IPv6 URL"),
+ pytest.param(
+ "http://[2607:f8b0:4005:805::200e/*",
+ "Invalid IPv6 URL",
+ id='host-ipv6-no-closing',
+ ),
# Two closing brackets (`]]`).
- pytest.param("http://[2607:f8b0:4005:805::200e]]/*", "Invalid IPv6 URL", marks=pytest.mark.xfail(reason="https://bugs.python.org/issue34360")),
+ pytest.param(
+ "http://[2607:f8b0:4005:805::200e]]/*",
+ "Invalid IPv6 URL",
+ marks=pytest.mark.xfail(reason="https://bugs.python.org/issue34360"),
+ id='host-ipv6-two-closing',
+ ),
# Two open brackets (`[[`).
- ("http://[[2607:f8b0:4005:805::200e]/*", r"""Expected '\]' to match '\[' in hostname; source was "\[2607:f8b0:4005:805::200e"; host = """""),
+ pytest.param(
+ "http://[[2607:f8b0:4005:805::200e]/*",
+ r"""Expected '\]' to match '\[' in hostname; source was "\[2607:f8b0:4005:805::200e"; host = """"",
+ id='host-ipv6-two-open',
+ ),
# Too few colons in the last chunk.
- ("http://[2607:f8b0:4005:805:200e]/*", 'Invalid IPv6 address; source was "2607:f8b0:4005:805:200e"; host = ""'),
+ pytest.param(
+ "http://[2607:f8b0:4005:805:200e]/*",
+ 'Invalid IPv6 address; source was "2607:f8b0:4005:805:200e"; host = ""',
+ id='host-ipv6-colons',
+ ),
# Non-hex piece.
- ("http://[2607:f8b0:4005:805:200e:12:bogus]/*", 'Invalid IPv6 address; source was "2607:f8b0:4005:805:200e:12:bogus"; host = ""'),
+ pytest.param(
+ "http://[2607:f8b0:4005:805:200e:12:bogus]/*",
+ 'Invalid IPv6 address; source was "2607:f8b0:4005:805:200e:12:bogus"; host = ""',
+ id='host-ipv6-non-hex',
+ ),
### Chromium: kInvalidHostWildcard
## TEST(ExtensionURLPatternTest, ParseInvalid)
- ("http://*foo/bar", "Invalid host wildcard"),
- ("http://foo.*.bar/baz", "Invalid host wildcard"),
- ("http://fo.*.ba:123/baz", "Invalid host wildcard"),
- ("http://foo.*/bar", "Invalid host wildcard"),
+ pytest.param("http://*foo/bar", "Invalid host wildcard", id='host-wildcard-no-dot'),
+ pytest.param(
+ "http://foo.*.bar/baz",
+ "Invalid host wildcard",
+ id='host-wildcard-middle',
+ ),
+ pytest.param(
+ "http://fo.*.ba:123/baz",
+ "Invalid host wildcard",
+ id='host-wildcard-middle-port',
+ ),
+ pytest.param("http://foo.*/bar", "Invalid host wildcard", id='host-wildcard-end'),
### Chromium: kInvalidPort
## TEST(ExtensionURLPatternTest, Ports)
- ("http://foo:/", "Invalid port: Port is empty"),
- ("http://*.foo:/", "Invalid port: Port is empty"),
- ("http://foo:com/", "Invalid port: .* 'com'"),
- ("http://foo:123456/", "Invalid port: Port out of range 0-65535"),
- ("http://foo:80:80/monkey", "Invalid port: .* '80:80'"),
- ("chrome://foo:1234/bar", "Ports are unsupported with chrome scheme"),
+ pytest.param("http://foo:/", "Invalid port: Port is empty", id='port-empty'),
+ pytest.param(
+ "http://*.foo:/",
+ "Invalid port: Port is empty",
+ id='port-empty-wildcard',
+ ),
+ pytest.param("http://foo:com/", "Invalid port: .* 'com'", id='port-alpha'),
+ pytest.param(
+ "http://foo:123456/",
+ "Invalid port: Port out of range 0-65535",
+ id='port-range',
+ ),
+ pytest.param(
+ "http://foo:80:80/monkey",
+ "Invalid port: .* '80:80'",
+ id='port-double',
+ ),
+ pytest.param(
+ "chrome://foo:1234/bar",
+ "Ports are unsupported with chrome scheme",
+ id='port-chrome',
+ ),
# No port specified, but port separator.
- ("http://[2607:f8b0:4005:805::200e]:/*", "Invalid port: Port is empty"),
+ pytest.param(
+ "http://[2607:f8b0:4005:805::200e]:/*",
+ "Invalid port: Port is empty",
+ id='port-empty-ipv6',
+ ),
### Additional tests
- ("http://[", "Invalid IPv6 URL"),
- ("http://[fc2e::bb88::edac]", 'Invalid IPv6 address; source was "fc2e::bb88::edac"; host = ""'),
- ("http://[fc2e:0e35:bb88::edac:fc2e:0e35:bb88:edac]", 'Invalid IPv6 address; source was "fc2e:0e35:bb88::edac:fc2e:0e35:bb88:edac"; host = ""'),
- ("http://[fc2e:0e35:bb88:af:edac:fc2e:0e35:bb88:edac]", 'Invalid IPv6 address; source was "fc2e:0e35:bb88:af:edac:fc2e:0e35:bb88:edac"; host = ""'),
- ("http://[127.0.0.1:fc2e::bb88:edac]", r'Invalid IPv6 address; source was "127\.0\.0\.1:fc2e::bb88:edac'),
- ("http://[fc2e::bb88", "Invalid IPv6 URL"),
- ("http://[fc2e:bb88:edac]", 'Invalid IPv6 address; source was "fc2e:bb88:edac"; host = ""'),
- ("http://[fc2e:bb88:edac::z]", 'Invalid IPv6 address; source was "fc2e:bb88:edac::z"; host = ""'),
- ("http://[fc2e:bb88:edac::2]:2a2", "Invalid port: .* '2a2'"),
- ("://", "Missing scheme"),
+ pytest.param("http://[", "Invalid IPv6 URL", id='ipv6-single-open'),
+ pytest.param(
+ "http://[fc2e::bb88::edac]",
+ 'Invalid IPv6 address; source was "fc2e::bb88::edac"; host = ""',
+ id='ipv6-double-double',
+ ),
+ pytest.param(
+ "http://[fc2e:0e35:bb88::edac:fc2e:0e35:bb88:edac]",
+ 'Invalid IPv6 address; source was "fc2e:0e35:bb88::edac:fc2e:0e35:bb88:edac"; host = ""',
+ id='ipv6-long-double',
+ ),
+ pytest.param(
+ "http://[fc2e:0e35:bb88:af:edac:fc2e:0e35:bb88:edac]",
+ 'Invalid IPv6 address; source was "fc2e:0e35:bb88:af:edac:fc2e:0e35:bb88:edac"; host = ""',
+ id='ipv6-long',
+ ),
+ pytest.param(
+ "http://[127.0.0.1:fc2e::bb88:edac]",
+ r'Invalid IPv6 address; source was "127\.0\.0\.1:fc2e::bb88:edac',
+ id='ipv6-ipv4',
+ ),
+ pytest.param("http://[fc2e::bb88", "Invalid IPv6 URL", id='ipv6-trailing'),
+ pytest.param(
+ "http://[fc2e:bb88:edac]",
+ 'Invalid IPv6 address; source was "fc2e:bb88:edac"; host = ""',
+ id='ipv6-short',
+ ),
+ pytest.param(
+ "http://[fc2e:bb88:edac::z]",
+ 'Invalid IPv6 address; source was "fc2e:bb88:edac::z"; host = ""',
+ id='ipv6-z',
+ ),
+ pytest.param(
+ "http://[fc2e:bb88:edac::2]:2a2",
+ "Invalid port: .* '2a2'",
+ id='ipv6-port',
+ ),
+ pytest.param("://", "Missing scheme", id='scheme-naked'),
])
def test_invalid_patterns(pattern, error):
with pytest.raises(urlmatch.ParseError, match=error):
urlmatch.UrlPattern(pattern)
+# pylint: enable=line-too-long
+
@pytest.mark.parametrize('host', ['.', ' ', ' .', '. ', '. .', '. . .', ' . '])
def test_whitespace_hosts(host):
diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py
index 6c57cb3d3..1ffbe3c09 100644
--- a/tests/unit/utils/test_version.py
+++ b/tests/unit/utils/test_version.py
@@ -484,17 +484,20 @@ class TestGitStrSubprocess:
@needs_git
def test_real_git(self, git_repo):
"""Test with a real git repository."""
- branch_name = subprocess.run(
- ['git', 'config', 'init.defaultBranch'],
- check=False,
- stdout=subprocess.PIPE,
- encoding='utf-8',
- ).stdout.strip()
- if not branch_name:
- branch_name = 'master'
+ def _get_git_setting(name, default):
+ return subprocess.run(
+ ['git', 'config', '--default', default, name],
+ check=True,
+ stdout=subprocess.PIPE,
+ encoding='utf-8',
+ ).stdout.strip()
ret = version._git_str_subprocess(str(git_repo))
- assert ret == f'6e4b65a on {branch_name} (1970-01-01 01:00:00 +0100)'
+ branch_name = _get_git_setting('init.defaultBranch', 'master')
+ abbrev_length = int(_get_git_setting('core.abbrev', '7'))
+ expected_sha = '6e4b65a529c0ab78fb370c1527d5809f7436b8f3'[:abbrev_length]
+
+ assert ret == f'{expected_sha} on {branch_name} (1970-01-01 01:00:00 +0100)'
def test_missing_dir(self, tmp_path):
"""Test with a directory which doesn't exist."""
diff --git a/tox.ini b/tox.ini
index 271bf4241..f52d7b158 100644
--- a/tox.ini
+++ b/tox.ini
@@ -13,7 +13,6 @@ minversion = 3.15
setenv =
PYTEST_QT_API=pyqt5
pyqt{,512,513,514,515,5150}: LINK_PYQT_SKIP=true
- pyqt{,512,513,514,515,5150}: QUTE_BDD_WEBENGINE=true
cov: PYTEST_ADDOPTS=--cov --cov-report xml --cov-report=html --cov-report=
passenv = PYTHON DISPLAY XAUTHORITY HOME USERNAME USER CI XDG_* QUTE_* DOCKER QT_QUICK_BACKEND PY_COLORS DBUS_SESSION_BUS_ADDRESS
basepython =
@@ -42,7 +41,6 @@ commands =
basepython = {env:PYTHON:python3}
setenv =
PYTEST_QT_API=pyqt5
- QUTE_BDD_WEBENGINE=true
pip_pre = true
deps = -r{toxinidir}/misc/requirements/requirements-tests-bleeding.txt
commands_pre = pip install --index-url https://www.riverbankcomputing.com/pypi/simple/ --pre --upgrade PyQt5 PyQtWebEngine