Compare commits
26 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
469bca1777 | |
|
|
f80ce9a325 | |
|
|
dcb1ca35ae | |
|
|
c6ebf26223 | |
|
|
ab566cdb03 | |
|
|
1167b5c3e8 | |
|
|
7d93098fd0 | |
|
|
73ce4ef9e1 | |
|
|
a44ac66ede | |
|
|
14a152f246 | |
|
|
c684e5fd3a | |
|
|
f675a958e5 | |
|
|
1e5184bc71 | |
|
|
d19375b664 | |
|
|
55a2f68d95 | |
|
|
57a8f13393 | |
|
|
02619e3c84 | |
|
|
078f1920a1 | |
|
|
fcb483d36f | |
|
|
d64d59502a | |
|
|
951ab7902e | |
|
|
44ee8272d8 | |
|
|
19c01aa772 | |
|
|
bdf9f121ee | |
|
|
292337fbdd | |
|
|
8232d38492 |
|
|
@ -1,5 +1,5 @@
|
|||
[bumpversion]
|
||||
current_version = 2.2.0
|
||||
current_version = 2.2.1
|
||||
commit = True
|
||||
message = Release v{new_version}
|
||||
tag = True
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
-------------------
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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"/>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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."
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
||||
|
|
|
|||
|
|
@ -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()}")
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
},
|
||||
});
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Reference in New Issue