Compare commits

...

26 Commits
main ... v2.2.1

Author SHA1 Message Date
Florian Bruhin 469bca1777 Release v2.2.1 2021-04-29 13:32:59 +02:00
Florian Bruhin f80ce9a325 Update changelog from master 2021-04-29 13:32:37 +02:00
Florian Bruhin dcb1ca35ae scripts: Add --no-confirm to build_release
(cherry picked from commit 9aa8740ec9)
2021-04-29 09:36:23 +02:00
Florian Bruhin c6ebf26223 ci: Fix CodeQL
(cherry picked from commit 4751890acb)
2021-04-29 09:35:17 +02:00
Florian Bruhin ab566cdb03 ci: Lock down workflows
Closes #6430

(cherry picked from commit 8023b8c8fe)
2021-04-29 09:35:09 +02:00
Florian Bruhin 1167b5c3e8 Add QUTE_QTWEBENGINE_VERSION_OVERRIDE
See https://github.com/NixOS/nixpkgs/pull/119376#issuecomment-820073044

(cherry picked from commit febb921040)
2021-04-29 09:34:51 +02:00
Florian Bruhin 7d93098fd0 tests: Fix test_version with git's init.defaultBranch
(cherry picked from commit 32604a6651)
2021-04-29 09:34:51 +02:00
afreakk 73ce4ef9e1 qute-pass: dont run pass twice when otp-only
(cherry picked from commit b04f99bcfc)
2021-04-28 08:19:48 +02:00
Nicholas Schwab a44ac66ede Improved readability of statusbar.widgets documentation.
(cherry picked from commit 38c5eba3e1)
2021-04-28 08:19:45 +02:00
Nicholas Schwab 14a152f246 Added text: to valid values of statusbar.widgets, making the
documentation more uniform.

(cherry picked from commit a083728168)
2021-04-28 08:19:43 +02:00
Florian Bruhin c684e5fd3a Add a site-specific quirk for Discord
Closes #4379

(cherry picked from commit be37524f47)
2021-04-28 08:19:37 +02:00
Florian Bruhin f675a958e5 Revert "Set print resolution to 300dpi"
This reverts commit 1e5184bc71.
2021-04-23 11:45:22 +02:00
Florian Bruhin 1e5184bc71 Set print resolution to 300dpi
See https://codereview.qt-project.org/c/qt/qtwebengine/+/344042

(cherry picked from commit 2e4ca779c6)
2021-04-23 11:22:33 +02:00
Florian Bruhin d19375b664 Fix tests on Windows
(cherry picked from commit 0ee169e497)
2021-04-23 11:11:00 +02:00
Florian Bruhin 55a2f68d95 Fix :spawn -u -o
Fixes #6407

(cherry picked from commit c7b3559d82)
2021-04-23 10:43:15 +02:00
Florian Bruhin 57a8f13393 Update PE checksum patching after PyInstaller update
(cherry picked from commit b1265cbeff)
2021-04-22 20:47:31 +02:00
Florian Bruhin 02619e3c84 Update PyInstaller from master 2021-04-22 20:47:07 +02:00
Florian Bruhin 078f1920a1 ci: Pin Python 3.10 to Alpha 7
See https://github.com/actions/setup-python/issues/207

pytest isn't ready yet:
https://github.com/pytest-dev/pytest/issues/8539

(cherry picked from commit 0c1414c6aa)
2021-04-19 11:45:42 +02:00
afreakk fcb483d36f qute-pass: extract username/pw only when needed
(cherry picked from commit efcb379872)
2021-04-19 11:28:05 +02:00
frank shin d64d59502a address PR comment
(cherry picked from commit 49e858e7d4)
2021-04-19 11:28:05 +02:00
frank shin 951ab7902e Check bitwarden CLI tool return code instead of stderr to check for error
(cherry picked from commit 909230a8ac)
2021-04-19 11:28:05 +02:00
Florian Bruhin 44ee8272d8 requirements: Fully remove python_version marker for adblock
See https://github.com/ArniDagur/python-adblock/issues/28

Follow-up to de4fff3866
(cherry picked from commit ffdee8534d)
Also updates adblock from 3b76a0d4b9
2021-04-19 11:27:13 +02:00
Florian Bruhin 19c01aa772 mkvenv: Handle failing ldconfig
(cherry picked from commit 1b4daf7c37)
2021-04-17 10:44:35 +02:00
Florian Bruhin bdf9f121ee notifications: Ignore KDE's ExcessNotificationGeneration
(cherry picked from commit 9fdfd3b4c0)
2021-04-17 10:44:35 +02:00
Florian Bruhin 292337fbdd notifications: Show adapter errors to users
Otherwise their notifications could suddenly stop working or otherwise
change apperance.

(cherry picked from commit ebf9619583)
2021-04-13 17:39:42 +02:00
Florian Bruhin 8232d38492 notifications: Handle MaxNotificationsExceeded error from GNOME Flashback
(cherry picked from commit 2cfc64579a)
2021-04-13 17:39:42 +02:00
24 changed files with 205 additions and 74 deletions

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2.2.0
current_version = 2.2.1
commit = True
message = Release v{new_version}
tag = True

View File

@ -25,6 +25,8 @@ jobs:
options: --privileged --tty
steps:
- uses: actions/checkout@v2
with:
persist-credentials: false
- name: Set up problem matchers
run: "python scripts/dev/ci/problemmatchers.py py3 ${{ runner.temp }}"
- name: Run tox
@ -51,6 +53,8 @@ jobs:
timeout-minutes: 30
steps:
- uses: actions/checkout@v2
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v2
with:
@ -61,6 +65,7 @@ jobs:
repository: asciidoc-py/asciidoc-py
ref: '9.x'
path: asciidoc
persist-credentials: false
- name: Move asciidoc out of the repo
run: mv asciidoc ..
- name: Install dependencies

View File

@ -32,6 +32,8 @@ jobs:
- testenv: yamllint
steps:
- uses: actions/checkout@v2
with:
persist-credentials: false
- uses: actions/cache@v2
with:
path: |
@ -88,6 +90,8 @@ jobs:
options: --privileged --tty
steps:
- uses: actions/checkout@v2
with:
persist-credentials: false
- name: Set up problem matchers
run: "python scripts/dev/ci/problemmatchers.py py38 ${{ runner.temp }}"
- name: Run tox
@ -124,7 +128,7 @@ jobs:
### PyQt 5.15 (Python 3.10)
- testenv: py310-pyqt515
os: ubuntu-20.04
python: 3.10-dev
python: 3.10.0-alpha.7
### macOS: PyQt 5.15 (Python 3.9 to match PyInstaller env)
- testenv: py39-pyqt515
os: macos-10.15
@ -142,6 +146,8 @@ jobs:
runs-on: "${{ matrix.os }}"
steps:
- uses: actions/checkout@v2
with:
persist-credentials: false
- uses: actions/cache@v2
with:
path: |
@ -181,11 +187,15 @@ jobs:
codeql:
if: "!contains(github.event.head_commit.message, '[ci skip]')"
permissions:
security-events: write
timeout-minutes: 30
runs-on: ubuntu-20.04
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:

View File

@ -19,6 +19,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
persist-credentials: false
- name: Set up Python 3.7
uses: actions/setup-python@v2
with:

View File

@ -15,6 +15,37 @@ 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.
[[v2.2.1]]
v2.2.1 (2021-04-29)
-------------------
Changed
~~~~~~~
- When an error occurs in a notification presenter, qutebrowser now shows that
error in the statusbar instead of just logging it.
- New site-specific-quirk for Discord logging users out when using vertical
ttabs (yes, really)
Fixed
~~~~~
- Certain errors from notification daemons are now displayed as non-fatal
errors instead of qutebrowser crashing:
* With the legacy GNOME Flashback notification daemon (not GNOME Shell), when
more than 20 notifications are currently shown.
* With the KDE Plasma notification daemon, when the same notification is
shown twice (with <1s delay).
- The `mkvenv.py` script now works when `ldconfig -p` is failing.
- Running `:spawn -u -o` broke in v2.2.0 and now works properly again.
- Fixes in userscripts:
* The `qute-bitwarden` userscript now still consumes returned data if the
Bitwarden CLI showed a warning but exited with a 0 (successful) exit code.
* The `qute-pass` userscript now doesn't try to match a username with
`--password-only`, and error messages with invalid patterns are improved.
* The `qute-pass` userscript now avoids running `pass` twice when `--otp-only`
is used.
[[v2.2.0]]
v2.2.0 (2021-04-13)
-------------------

View File

@ -2693,6 +2693,7 @@ Valid values:
* +ua-google+
* +ua-slack+
* +js-whatsapp-web+
* +js-discord+
* +js-string-replaceall+
* +js-globalthis+
* +js-object-fromentries+
@ -3973,7 +3974,6 @@ Default: +pass:[always]+
[[statusbar.widgets]]
=== statusbar.widgets
List of widgets displayed in the statusbar.
In addition to the listed values there is also the possibility to add `text:foo` widgets that will display `foo`.
Type: <<types,List of StatusbarWidget>>
@ -3986,6 +3986,7 @@ Valid values:
* +tabs+: Current active tab, e.g. `2`.
* +keypress+: Display pressed keys when composing a vi command.
* +progress+: Progress bar for the current page loading.
* +text:foo+: Display the static text after the colon, `foo` in the example.
Default:

View File

@ -44,6 +44,7 @@
</content_rating>
<releases>
<!-- Add new releases here -->
<release version="2.2.1" date="2021-04-29"/>
<release version="2.2.0" date="2021-04-13"/>
<release version="2.1.1" date="2021-04-01"/>
<release version="2.1.0" date="2021-03-12"/>

View File

@ -1,5 +1,5 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
altgraph==0.17
pyinstaller==4.2
pyinstaller==4.3
pyinstaller-hooks-contrib==2021.1

View File

@ -18,6 +18,3 @@ typing_extensions # from importlib-metadata
#@ markers: importlib-metadata python_version<"3.8"
#@ markers: typing_extensions python_version<"3.8"
#@ markers: dataclasses python_version<"3.7"
# https://github.com/ArniDagur/python-adblock/issues/28
#@ markers: adblock python_version!="3.10"

View File

@ -157,6 +157,8 @@ def pass_(domain, encoding, auto_lock):
if err:
msg = 'Bitwarden CLI returned for {:s} - {:s}'.format(domain, err)
stderr(msg)
if process.returncode:
return '[]'
out = process.stdout.decode(encoding).strip()
@ -177,6 +179,8 @@ def get_totp_code(selection_id, domain_name, encoding, auto_lock):
# domain_name instead of selection_id to make it more user-friendly
msg = 'Bitwarden CLI returned for {:s} - {:s}'.format(domain_name, err)
stderr(msg)
if process.returncode:
return '[]'
out = process.stdout.decode(encoding).strip()

View File

@ -109,6 +109,14 @@ class ExitCodes(enum.IntEnum):
COULD_NOT_MATCH_PASSWORD = 4
class CouldNotMatchUsername(Exception):
pass
class CouldNotMatchPassword(Exception):
pass
def qute_command(command):
with open(os.environ['QUTE_FIFO'], 'w') as fifo:
fifo.write(command + '\n')
@ -174,6 +182,26 @@ def fake_key_raw(text):
qute_command('fake-key {}'.format(sequence))
def extract_password(secret, pattern):
match = re.match(pattern, secret)
if not match:
raise CouldNotMatchPassword("Pattern did not match target")
try:
return match.group(1)
except IndexError:
raise CouldNotMatchPassword("Pattern did not contain capture group, please use capture group. Example: (.*)")
def extract_username(target, pattern):
match = re.search(pattern, target, re.MULTILINE)
if not match:
raise CouldNotMatchUsername("Pattern did not match target")
try:
return match.group(1)
except IndexError:
raise CouldNotMatchUsername("Pattern did not contain capture group, please use capture group. Example: (.*)")
def main(arguments):
if not arguments.url:
argument_parser.print_help()
@ -212,39 +240,32 @@ def main(arguments):
if not selection:
return ExitCodes.SUCCESS
# If username-target is path and user asked for username-only, we don't need to run pass
# If username-target is path and user asked for username-only, we don't need to run pass.
# Or if using otp-only, it will run pass on its own.
secret = None
if not (arguments.username_target == 'path' and arguments.username_only):
if not (arguments.username_target == 'path' and arguments.username_only) and not arguments.otp_only:
secret = pass_(selection)
# Match password
match = re.match(arguments.password_pattern, secret)
if not match:
stderr('Failed to match password pattern on secret!')
return ExitCodes.COULD_NOT_MATCH_PASSWORD
password = match.group(1)
# Match username
target = selection if arguments.username_target == 'path' else secret
match = re.search(arguments.username_pattern, target, re.MULTILINE)
if not match:
stderr('Failed to match username pattern on {}!'.format(arguments.username_target))
username_target = selection if arguments.username_target == 'path' else secret
try:
if arguments.username_only:
fake_key_raw(extract_username(username_target, arguments.username_pattern))
elif arguments.password_only:
fake_key_raw(extract_password(secret, arguments.password_pattern))
elif arguments.otp_only:
otp = pass_otp(selection)
fake_key_raw(otp)
else:
# Enter username and password using fake-key and <Tab> (which seems to work almost universally), then switch
# back into insert-mode, so the form can be directly submitted by hitting enter afterwards
fake_key_raw(extract_username(username_target, arguments.username_pattern))
qute_command('fake-key <Tab>')
fake_key_raw(extract_password(secret, arguments.password_pattern))
except CouldNotMatchPassword as e:
stderr('Failed to match password, target: secret, error: {}'.format(e))
return ExitCodes.COULD_NOT_MATCH_PASSWORD
except CouldNotMatchUsername as e:
stderr('Failed to match username, target: {}, error: {}'.format(arguments.username_target, e))
return ExitCodes.COULD_NOT_MATCH_USERNAME
username = match.group(1)
if arguments.username_only:
fake_key_raw(username)
elif arguments.password_only:
fake_key_raw(password)
elif arguments.otp_only:
otp = pass_otp(selection)
fake_key_raw(otp)
else:
# Enter username and password using fake-key and <Tab> (which seems to work almost universally), then switch
# back into insert-mode, so the form can be directly submitted by hitting enter afterwards
fake_key_raw(username)
qute_command('fake-key <Tab>')
fake_key_raw(password)
if arguments.insert_mode:
qute_command('mode-enter insert')

View File

@ -26,7 +26,7 @@ __copyright__ = "Copyright 2014-2021 Florian Bruhin (The Compiler)"
__license__ = "GPL"
__maintainer__ = __author__
__email__ = "mail@qutebrowser.org"
__version__ = "2.2.0"
__version__ = "2.2.1"
__version_info__ = tuple(int(part) for part in __version__.split('.'))
__description__ = "A keyboard-driven, vim-like browser based on PyQt5."

View File

@ -1099,8 +1099,7 @@ class CommandDispatcher:
try:
runner = self._run_userscript(
s, cmd, args, verbose, output_messages, count)
runner.finished.connect(functools.partial(
_on_proc_finished, runner.proc))
runner.finished.connect(_on_proc_finished)
except cmdutils.CommandError as e:
message.error(str(e))

View File

@ -399,8 +399,7 @@ class NotificationBridgePresenter(QObject):
# Error during setup
return
log.misc.error(
f"Notification error from {self._adapter.NAME} adapter: {error}")
message.error(f"Notification error from {self._adapter.NAME} adapter: {error}")
self._drop_adapter()
@ -693,6 +692,20 @@ class DBusNotificationAdapter(AbstractNotificationAdapter):
SPEC_VERSION = "1.2" # Released in January 2011, still current in March 2021.
NAME = "libnotify"
_NON_FATAL_ERRORS = {
# notification daemon is gone
"org.freedesktop.DBus.Error.NoReply",
# https://gitlab.gnome.org/GNOME/gnome-flashback/-/blob/3.40.0/gnome-flashback/libnotifications/nd-daemon.c#L178-187
# Exceeded maximum number of notifications
"org.freedesktop.Notifications.MaxNotificationsExceeded",
# https://bugs.kde.org/show_bug.cgi?id=409157
# https://github.com/KDE/plasma-workspace/blob/v5.21.4/libnotificationmanager/server_p.cpp#L227-L237
# Created too many similar notifications in quick succession
"org.freedesktop.Notifications.Error.ExcessNotificationGeneration",
}
def __init__(self, parent: QObject = None) -> None:
super().__init__(bridge)
if not qtutils.version_check('5.14'):
@ -878,8 +891,8 @@ class DBusNotificationAdapter(AbstractNotificationAdapter):
if msg.type() == QDBusMessage.ErrorMessage:
err = msg.errorName()
if err == "org.freedesktop.DBus.Error.NoReply":
self.error.emit(msg.errorMessage()) # notification daemon is gone
if err in self._NON_FATAL_ERRORS:
self.error.emit(msg.errorMessage())
return
raise Error(f"Got DBus error: {err} - {msg.errorMessage()}")

View File

@ -1152,6 +1152,7 @@ class _WebEngineScripts(QObject):
injection_point=QWebEngineScript.DocumentReady,
world=QWebEngineScript.ApplicationWorld,
),
_Quirk('discord'),
_Quirk(
'string_replaceall',
predicate=versions.webengine < utils.VersionNumber(5, 15, 3),

View File

@ -108,10 +108,11 @@ class _BaseUserscriptRunner(QObject):
Signals:
got_cmd: Emitted when a new command arrived and should be executed.
finished: Emitted when the userscript finished running.
arg: The finished GUIProcess object.
"""
got_cmd = pyqtSignal(str)
finished = pyqtSignal()
finished = pyqtSignal(guiprocess.GUIProcess)
def __init__(self, parent=None):
super().__init__(parent)
@ -288,8 +289,10 @@ class _POSIXUserscriptRunner(_BaseUserscriptRunner):
self._reader.cleanup()
self._reader.deleteLater()
self._reader = None
proc = self.proc
super()._cleanup()
self.finished.emit()
self.finished.emit(proc)
class _WindowsUserscriptRunner(_BaseUserscriptRunner):
@ -321,8 +324,9 @@ class _WindowsUserscriptRunner(_BaseUserscriptRunner):
log.misc.error("Invalid unicode in userscript output: {}"
.format(e))
proc = self.proc
super()._cleanup()
self.finished.emit()
self.finished.emit(proc)
@pyqtSlot()
def on_proc_error(self):

View File

@ -546,6 +546,7 @@ content.site_specific_quirks.skip:
- ua-google
- ua-slack
- js-whatsapp-web
- js-discord
- js-string-replaceall
- js-globalthis
- js-object-fromentries
@ -1933,13 +1934,10 @@ statusbar.widgets:
- tabs: "Current active tab, e.g. `2`."
- keypress: "Display pressed keys when composing a vi command."
- progress: "Progress bar for the current page loading."
- 'text:foo': "Display the static text after the colon, `foo` in the example."
none_ok: true
default: ['keypress', 'url', 'scroll', 'history', 'tabs', 'progress']
desc: >-
List of widgets displayed in the statusbar.
In addition to the listed values there is also the possibility
to add `text:foo` widgets that will display `foo`.
desc: "List of widgets displayed in the statusbar."
## tabs

View File

@ -0,0 +1,14 @@
// ==UserScript==
// @include https://discord.com/*
// ==/UserScript==
// Workaround for Discord's silly bot detection (or whatever it is logging
// people out with vertical tabs).
"use strict";
Object.defineProperty(window, "outerWidth", {
get() {
return window.innerWidth;
},
});

View File

@ -710,7 +710,7 @@ class WebEngineVersions:
)
@classmethod
def from_qt(cls, qt_version: str) -> 'WebEngineVersions':
def from_qt(cls, qt_version: str, *, source: str = 'Qt') -> 'WebEngineVersions':
"""Get the versions based on the Qt version.
This is called if we don't have PYQT_WEBENGINE_VERSION, i.e. with PyQt 5.12.
@ -719,7 +719,7 @@ class WebEngineVersions:
return cls(
webengine=parsed,
chromium=cls._infer_chromium_version(parsed),
source='Qt',
source=source,
)
@ -750,6 +750,10 @@ def qtwebengine_versions(avoid_init: bool = False) -> WebEngineVersions:
if webenginesettings.parsed_user_agent is not None:
return WebEngineVersions.from_ua(webenginesettings.parsed_user_agent)
override = os.environ.get('QUTE_QTWEBENGINE_VERSION_OVERRIDE')
if override is not None:
return WebEngineVersions.from_qt(override, source='override')
versions = elf.parse_webenginecore()
if versions is not None:
return WebEngineVersions.from_elf(versions)

View File

@ -1,6 +1,6 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
adblock==0.4.3 ; python_version!="3.10"
adblock==0.4.4
colorama==0.4.4
dataclasses==0.6 ; python_version<"3.7"
importlib-metadata==3.10.0 ; python_version<"3.8"

View File

@ -206,21 +206,11 @@ def smoke_test(executable, debug):
raise Exception("\n".join(lines))
def patch_windows_exe(exe_path):
"""Make sure the Windows .exe has a correct checksum.
WORKAROUND for https://github.com/pyinstaller/pyinstaller/issues/5579
"""
def verify_windows_exe(exe_path):
"""Make sure the Windows .exe has a correct checksum."""
import pefile
pe = pefile.PE(exe_path)
# If this fails, a PyInstaller upgrade fixed things, and we can remove the
# workaround. Would be a good idea to keep the check, though.
assert not pe.verify_checksum()
pe.OPTIONAL_HEADER.CheckSum = pe.generate_checksum()
pe.close()
pe.write(exe_path)
assert pe.verify_checksum()
def patch_mac_app():
@ -364,8 +354,8 @@ def _build_windows_single(*, x64, skip_packaging, debug):
shutil.move(out_pyinstaller, outdir)
exe_path = os.path.join(outdir, 'qutebrowser.exe')
utils.print_title(f"Patching {human_arch} exe")
patch_windows_exe(exe_path)
utils.print_title(f"Verifying {human_arch} exe")
verify_windows_exe(exe_path)
utils.print_title(f"Running {human_arch} smoke test")
smoke_test(exe_path, debug=debug)
@ -617,6 +607,8 @@ def main():
nargs='?')
parser.add_argument('--upload', action='store_true', required=False,
help="Toggle to upload the release to GitHub.")
parser.add_argument('--no-confirm', action='store_true', required=False,
help="Skip confirmation before uploading.")
parser.add_argument('--skip-packaging', action='store_true', required=False,
help="Skip Windows installer/zip generation.")
parser.add_argument('--32bit', action='store_true', required=False,
@ -665,8 +657,10 @@ def main():
if args.upload:
version_tag = "v" + qutebrowser.__version__
utils.print_title("Press enter to release {}...".format(version_tag))
input()
if not args.no_confirm:
utils.print_title("Press enter to release {}...".format(version_tag))
input()
github_upload(artifacts, version_tag, gh_token=gh_token)
if upload_to_pypi:

View File

@ -271,7 +271,13 @@ def apply_xcb_util_workaround(
print("Workaround not needed: Not installing Qt 5.15.")
return
libs = _find_libs()
try:
libs = _find_libs()
except subprocess.CalledProcessError as e:
utils.print_error(
f'Workaround failed: ldconfig exited with status {e.returncode}')
return
abi_type = 'libc6,x86-64' # the only one PyQt wheels are available for
if ('libxcb-util.so.1', abi_type) in libs:

View File

@ -44,8 +44,14 @@ Feature: :spawn
When I run :spawn -u -m (echo-exe) Message 2
Then the message "Message 2" should be shown
Scenario: Running :spawn with -u -o
When I run :spawn -u -o (echo-exe) Message 3
And I wait for "load status for * url='qute://process/*'>: LoadStatus.success" in the log
Then the page should contain the plaintext "Message 3"
@posix
Scenario: Running :spawn with userscript
Given I clean up open tabs
When I open data/hello.txt
And I run :spawn -u (testdata)/userscripts/open_current_url
And I wait until data/hello.txt is loaded
@ -66,6 +72,7 @@ Feature: :spawn
@windows
Scenario: Running :spawn with userscript on Windows
Given I clean up open tabs
When I open data/hello.txt
And I run :spawn -u (testdata)/userscripts/open_current_url.bat
And I wait until data/hello.txt is loaded

View File

@ -484,8 +484,17 @@ 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'
ret = version._git_str_subprocess(str(git_repo))
assert ret == '6e4b65a on master (1970-01-01 01:00:00 +0100)'
assert ret == f'6e4b65a 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."""
@ -1165,6 +1174,16 @@ class TestChromiumVersion:
assert versions.source == 'importlib'
assert versions.webengine == expected
@pytest.mark.parametrize('override', [
utils.VersionNumber(5, 12, 10),
utils.VersionNumber(5, 15, 3),
])
def test_override(self, monkeypatch, override):
monkeypatch.setenv('QUTE_QTWEBENGINE_VERSION_OVERRIDE', str(override))
versions = version.qtwebengine_versions(avoid_init=True)
assert versions.source == 'override'
assert versions.webengine == override
@dataclasses.dataclass
class VersionParams: