Compare commits

...

575 Commits
v3.3.1 ... main

Author SHA1 Message Date
Florian Bruhin 7e3df43463 Disable child focus workaround on unaffected Qt versions
The workaround added for #7820 seems to cause datalist dropdowns to lose focus
on Wayland. Let's just disable the old workaround on Qt versions that are not affected
by the original issue, which seems to be Qt 6.6.3+.

Fixes #8831.
2026-01-04 22:25:49 +01:00
Florian Bruhin 9ae082b29b version: Add QtWebEngine 6.9.3 2026-01-04 22:25:49 +01:00
dependabot[bot] b417f2a23b build(deps): bump peter-evans/create-pull-request from 7 to 8
Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7 to 8.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/v7...v8)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-16 12:51:26 +01:00
dependabot[bot] 615cee7309 build(deps): bump actions/upload-artifact from 5 to 6
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-16 12:51:19 +01:00
dependabot[bot] 65c1ca9691 build(deps): bump actions/cache from 4 to 5
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-16 12:51:09 +01:00
qutebrowser bot 12bed611c5 Update dependencies 2025-12-15 17:05:29 +01:00
Florian Bruhin bc72687d7d Update changelog URLs 2025-12-08 16:55:52 +01:00
Florian Bruhin c32b7d4b60 Fix dependency update issues 2025-12-08 10:53:13 +01:00
qutebrowser bot 3f9ef123e7 Update dependencies 2025-12-08 04:29:09 +00:00
Florian Bruhin f2547f8a09 scripts: Make smoke test fail output less confusing 2025-11-30 18:46:03 +01:00
qutebrowser bot edd5114492 Release v3.6.3
(cherry picked from commit ee13dac738)
2025-11-30 17:37:53 +00:00
Florian Bruhin 184a242937 ci: Make sure git knows the main branch
Something seems to have changed about how sparse checkouts are done on GHA, so the main branch isn't found.
2025-11-30 18:35:05 +01:00
Florian Bruhin 17c19a09b7 build_release: Try to get more information on crashes
Currently CI crashes on macOS, but without any useful logs.
2025-11-30 18:11:25 +01:00
Florian Bruhin 88aa47c377 Add qt.workarounds.disable_accessibility setting
This disables accessibility with Qt 6.10.1, which
causes frequent segfaults.

Closes #8797
2025-11-30 17:54:33 +01:00
dependabot[bot] 0570545342 build(deps): bump actions/checkout from 5 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-30 00:15:59 +01:00
qutebrowser bot f408f20ad9 Release v3.6.2
(cherry picked from commit b2c5d5fa0d)
2025-11-27 20:57:13 +00:00
Florian Bruhin 500a8df209 Update user agents 2025-11-27 21:55:44 +01:00
Florian Bruhin 13d9904b90 Update changelog for v3.6.2 2025-11-27 21:29:21 +01:00
Florian Bruhin b3e4dba731 qtargs: Remove old workaround with Qt 6.10.1 2025-11-27 21:28:34 +01:00
qutebrowser bot 4164205663 Update dependencies 2025-11-27 17:21:32 +01:00
qutebrowser bot f5e2660890 Update dependencies 2025-11-24 16:37:39 +01:00
Florian Bruhin 69f3882ce3 tests: Skip hangouts extension test on Qt 5 2025-11-23 11:42:49 +01:00
Florian Bruhin 8e42727d31 Update changelog 2025-11-22 10:40:30 +01:00
Florian Bruhin 31a5737c61 Avoid disabling off-the-record profile Hangouts extension with Qt 6.10.1
Otherwise this results in a crash, see #8785
2025-11-22 10:38:46 +01:00
Florian Bruhin 8ae5e3d83b version: Use correct profile for extension list
See #8785
2025-11-21 22:50:52 +01:00
Florian Bruhin 4f40a8b46b tests: Improve test_version output 2025-11-21 18:39:24 +01:00
Florian Bruhin 59a64af67f tests: Adjust permissions storage workaround for Qt 6.10.1 2025-11-21 18:35:03 +01:00
Florian Bruhin 66cbe0d9c9 Add QtWebEngine 6.10.1 security patch version 2025-11-21 18:31:43 +01:00
Florian Bruhin 0ef5053a65 tests: Stabilize flaky session scrolling test
Equivalent of d8079515fa
See #5390
2025-11-18 15:00:20 +01:00
qutebrowser bot 6ddff3ae0d Update dependencies 2025-11-18 14:08:13 +01:00
Florian Bruhin 9316d428ef ci: Drop Archlinux Qt 5 images/jobs
For now, Qt 5 is still tested via the Qt 5.15 PyPI wheels.

See https://github.com/qutebrowser/qutebrowser/issues/8417#issuecomment-3495979318
https://lists.archlinux.org/archives/list/arch-dev-public@lists.archlinux.org/thread/U45C4RAW4IXVLO376XGFNLEGGFFXCULV/
2025-11-11 09:13:30 +01:00
Florian Bruhin 71ed8cdbf5 Update changelog 2025-11-11 09:09:05 +01:00
Florian Bruhin 62fdb15532 Merge commit 'bc191b798' 2025-11-11 09:07:00 +01:00
Florian Bruhin bc191b798d wmname: Remove trivial functions 2025-11-11 09:06:49 +01:00
Florian Bruhin f8fbb0609f Update changelog 2025-11-11 08:46:36 +01:00
Florian Bruhin 55fb26fce1 Revert "fix: change fullscreen state when switching tab"
This reverts commit b89bf07d1e.

This turned out to be annoying when enabling fullscreen manually and then
switching through tabs.
2025-11-11 08:45:55 +01:00
Jan Palus 25dc019886
Unify librarry loading for X11/Wayland wmname
libwayland-client.so is development symlink used during linking and there's no need to
have it installed (usually shipped in -devel/-dev packages) on user's machines. Instead
of hardcoding library file name, use same mechanism as in libX11 which let's Python
figure the details and share common logic between X11 and Wayland.

Fixes #8771
2025-11-11 00:51:05 +01:00
Florian Bruhin 81d7b6a74c tests: Use star-unpacking instead of itertools.chain
pytest will soon deprecate using a non-collection iterable in parametrize:
https://docs.pytest.org/en/latest/deprecations.html#parametrize-iterators
2025-11-10 13:02:26 +01:00
qutebrowser bot 6ec5504ab3 Update dependencies 2025-11-10 07:39:05 +01:00
Florian Bruhin 9b69c889ef doc: Add additional chrome:// pages 2025-11-07 11:45:51 +01:00
Florian Bruhin 4e87ef303f ci: Update macOS runners / versions
https://github.blog/changelog/2025-09-19-github-actions-macos-13-runner-image-is-closing-down/

- CI: Switch to macOS 15 Intel runner
  (macOS 14 is still tested with Apple Silicon)
- Nightly: Use macOS 15 Intel runner for nightly releases
  (macOS 14 would be better to align with actual Intel releases, but it is
  a -large runner, thus possibly metered)
- Releases: Use macOS 14 for Intel releases
  This is a -large runner, but releases don't happen often.
2025-11-05 16:51:43 +01:00
gesh 2f8234ee2e doc: Correct Arch Linux links
Arch hasn't been using the [community] repository for 9 months now[1],
correct the links for that.
Also, youtube-dl has been replaced in [extra] by yt-dlp[2][3], unsure
when -- I think this was in 2023?
Finally (and the trigger for this commit), given #8332, correct the
guidance on Arch Linux to point to pdfjs-legacy instead of pdfjs.

[1]: https://archlinux.org/news/cleaning-up-old-repositories/
[2]: https://aur.archlinux.org/packages/youtube-dl
[3]: https://archlinux.org/packages/extra/any/yt-dlp/
2025-11-05 14:26:04 +01:00
Florian Bruhin a8f0b47451 tests: Ignore more bogus Chromium messages 2025-11-03 18:32:17 +01:00
Florian Bruhin 4a5b7bd6e4 Update changelog 2025-11-03 18:10:24 +01:00
OmeletWithoutEgg b89bf07d1e fix: change fullscreen state when switching tab 2025-11-03 18:09:28 +01:00
Rebecca 70bf4689fc Fixed whitespace
Removed excess line of whitespace.
2025-11-03 18:09:01 +01:00
Rebecca 1cbb6fccf0 Fixed minor issue in configuration docs
The docs show an example for adding domain filtering for configuration options. However the example only matches the root of a domain rather than all pages on a domain which is for example, the default case when using the `tsh` shortcut to disable/enable javascript on a page.
2025-11-03 18:09:01 +01:00
Rebecca d3e4245d0f Improved logging for configuration loading
- When loading a configuration file, if the configuration uses domain filtering then the domain filter expression is logged in the debug log.
2025-11-03 18:09:01 +01:00
qutebrowser bot 3160048619 Release v3.6.1
(cherry picked from commit 2e5f805cce)
2025-11-03 15:30:02 +00:00
Florian Bruhin aa93eb1614 Adjust stack trace parsing for newer Python 2025-11-03 16:26:12 +01:00
qutebrowser bot df9cef3a58 Update dependencies 2025-11-03 06:33:33 +01:00
dependabot[bot] 214e2e9ac2 build(deps): bump actions/upload-artifact from 4 to 5
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 20:41:53 +01:00
qutebrowser bot 68574b88cc Update dependencies 2025-10-27 08:21:55 +01:00
Florian Bruhin 6e8e24050d Fix changelog 2025-10-26 23:02:14 +01:00
dependabot[bot] 5fe9bf97e3 build(deps): bump actions/setup-node from 5 to 6
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 5 to 6.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-25 22:36:25 +02:00
Florian Bruhin b646d606d7 Fix releasing focus when leaving command mode
The fix for #8223 in 6f21accfae
was misguided: We don't really care about the statusbar being hidden,
controlled release of keyboard focus needs to happen in any case where
we're hiding the command widget (as that's when we lose keyboard focus).

Fixes #8750.
2025-10-25 16:43:06 +02:00
Florian Bruhin 1e4ddc2c6b ci: Fix finding existing draft release 2025-10-24 17:02:41 +02:00
Florian Bruhin 3fce0518bd scripts: Avoid showing entire file tree diff in CI log 2025-10-24 17:00:19 +02:00
Florian Bruhin 3808ebfdb3 ci: Find existing draft release for reuploads 2025-10-24 16:23:03 +02:00
Florian Bruhin 0421aacd64 ci: Check out release branch for reuploads 2025-10-24 15:45:15 +02:00
Florian Bruhin 0c2a673e27 scripts: Clean up build_release 2025-10-24 15:06:20 +02:00
Florian Bruhin afa456f396 ci: Skip existing artifacts when reuploading
After a release failed and we want to retry,
some assets might already have been uploaded.

Skip those instead of attempting to reupload.
2025-10-24 14:53:40 +02:00
Florian Bruhin 461077b6cf ci: Fix reupload in script 2025-10-24 14:34:20 +02:00
Florian Bruhin e208f5e121 ci: Add ability to reupload after borked release 2025-10-24 14:33:24 +02:00
Florian Bruhin 0f320051e0 scripts: Ignore another line during smoke tests 2025-10-24 14:17:29 +02:00
Florian Bruhin ee40f13a30 Update release checklist
minor releases happen far more often
2025-10-24 14:17:29 +02:00
qutebrowser bot 06c4fac54a Release v3.6.0 2025-10-24 12:11:30 +00:00
Florian Bruhin 1392d55f53 Update changelog 2025-10-24 13:53:21 +02:00
Florian Bruhin 269d81371d Update user agents 2025-10-24 13:50:15 +02:00
qutebrowser bot 346a59a6f0 Update dependencies 2025-10-24 12:28:48 +02:00
Florian Bruhin d8079515fa tests: Stabilize flaky scrolling test
See #5390
2025-10-24 12:26:00 +02:00
Florian Bruhin 294534cf66 tests: Mark found lines more clearly 2025-10-24 12:25:45 +02:00
Florian Bruhin da9bd515fd scripts: Update build-release ignores for Qt 6.10 2025-10-24 12:05:35 +02:00
Florian Bruhin 5ac0cb97a8 Fix Qt 5 2025-10-24 00:01:28 +02:00
Florian Bruhin 242cf2a22e version: Add basic info about loaded WebExtensions 2025-10-23 23:24:40 +02:00
Florian Bruhin 6f9cf43d6d Fix mypy 2025-10-22 22:03:33 +02:00
Florian Bruhin 00b3bba99a Qt 6.10: Disable Hangouts extension via API
See https://github.com/qutebrowser/qutebrowser/issues/8694#issuecomment-3276414407
2025-10-22 21:45:48 +02:00
Florian Bruhin 111178358a tests: Add new ignores for Qt 6.10 + GHA + Windows
See #8694
2025-10-22 17:36:45 +02:00
Florian Bruhin e098609a8a Add missing PyQt 6.10 requirement files 2025-10-22 17:01:19 +02:00
Florian Bruhin 721ba1e036 Add PyQt 6.10 release
Needs --extra-index-url due to PyQt6-WebEngine-Qt6 missing because of PyPI size limits.
2025-10-22 16:03:46 +02:00
Florian Bruhin c5e7a73ab7 tests: Set pythonpath in pytest.ini
Makes pytest work without PYTHONPATH=. if running outside tox.
2025-10-22 16:03:46 +02:00
qutebrowser bot 67db09a9c9 Update dependencies 2025-10-20 12:16:34 +02:00
dependabot[bot] 4925715dfc build(deps): bump github/codeql-action from 3 to 4
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-13 20:30:12 +02:00
Florian Bruhin 6f8576b343 Update changelog 2025-10-13 17:59:44 +02:00
qutebrowser bot 7bffed47ed Update dependencies 2025-10-13 18:00:02 +02:00
Florian Bruhin 642c5fe2fe ci: Fix python versions, take 2 2025-10-12 15:03:49 +02:00
Florian Bruhin 621f20adb3 configcommands: Fix :config-list-remove with invalid value 2025-10-12 14:53:45 +02:00
Florian Bruhin 9d80bc2076 Fix Dict configtype hypothesis test
If dict keys are too long for YAML, .from_str()
will fail with a YAML parse error.

Closes #8530
2025-10-12 14:43:03 +02:00
Florian Bruhin 88415c6aa0 ci: Adjust Python versions
Run Python 3.14 with PyQt 6.9 instead of 6.8, and remove -dev
2025-10-12 13:39:57 +02:00
Florian Bruhin 5c2076ab2d tests: Add Qt.Key.Key_Keyboard
New in Qt 6.10:
https://codereview.qt-project.org/c/qt/qtbase/+/605015
2025-10-12 13:32:01 +02:00
Florian Bruhin 7b2773814b Update changelog 2025-10-12 13:17:48 +02:00
Florian Bruhin 467b9a7d4a Add site-specific quirk for gitlab.gnome.org
Fixes #8509
2025-10-12 13:17:43 +02:00
Florian Bruhin 816b8aaa00 Adjust comment for workaround 2025-10-12 01:16:30 +02:00
Florian Bruhin d38b5a423e Update changelog 2025-10-11 21:17:03 +02:00
Florian Bruhin 7f45b178c9 Adjust imports 2025-10-11 20:49:52 +02:00
Florian Bruhin 26368f0b90 Work around per-domain UA header not working on redirects
See https://bugreports.qt.io/browse/QTBUG-140515
Fixes #8679
2025-10-11 20:49:19 +02:00
Teddy ff76871f4e replacing os.path with pathlib 2025-10-11 17:14:45 +02:00
Florian Bruhin 9ddbc964d4 Fix hardware acceleration on Wayland with Qt <= 6.9
Equivalent to https://codereview.qt-project.org/c/qt/qtwebengine/+/663568

    Specify native platform for ANGLE's EGL backend on Wayland

    Set EGL_PLATFORM=wayland to force ANGLE to obtain EGL display connection
    for wayland platform. Otherwise, the display connection for
    EGL_DEFAULT_DISPLAY may belong to a platform which Nvidia's EGL driver
    doesn't support. In case of unsupported platform, EGL may fallback to
    Mesa software renderer (LLVMPipe) disabling hardware acceleration in
    Chromium.

Fixes #8637
2025-10-10 23:33:28 +02:00
Florian Bruhin 2b4e5757b0 Reenable accelerated 3D canvas on QtWebEngine 6.8.2+
Qt 6.8.2 has a more fine-grained workaround:
https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/606122

This never seems to have it made to Qt 6.9+, but I can't seem to reproduce the
issue anymore (neither with PDF.js nor with Google Sheets), even on older
affected Qt versions, even on older Intel hardware. Maybe something else (mesa
etc.?) changed and this was fixed there?

Let's reenable this and find out if it breaks things again for someone.

Fixes #8346
See #7489, #8001, #8006
2025-10-10 23:07:09 +02:00
Florian Bruhin ddfd17d749 Fix focus issues with fullscreen notification
This is conceptually similar to the release_focus
signal added in 6aa19eb90f and
6f21accfae, but without having to thread the
signal through to TabbedBrowser and back.

Weirdly, doing self.setFocusPolicy(Qt.FocusPolicy.NoFocus) in
FullscreenNotification.__init__ did not help, so let's just set the focus
manually instead.

Fixes #8174.
Fixes #8625.
2025-10-10 20:46:48 +02:00
Florian Bruhin 6f21accfae Fix focus handling when closing hidden statusbar
From knezi's analysis in #8722:

    The problem was that in Qt, slots are called in the order of connection, so
    even though there's a code that tries to set up the focus correctly, it's
    run after the cmd widget is hidden and hence the focus is already moved and
    it doesn't work as expected.

Follow-up for #2236/#8024.
Fixes #8223.
Supersedes and closes #8722.
Also see #8625 and #8174 (which are not fixed by this).
2025-10-10 20:15:12 +02:00
Florian Bruhin 6b48ae4084 Update security patch version for Qt 6.10 release 2025-10-10 19:03:14 +02:00
Florian Bruhin e300327eea Update certifi changelog URL 2025-10-10 19:03:14 +02:00
mathis renaud 9d1dfcfe5c Make 'tox -e mypy' work again in tox.ini
Fix #8344
2025-10-10 19:03:16 +02:00
Florian Bruhin 897fc40f4d
Merge pull request #8725 from qutebrowser/update-dependencies
Update dependencies
2025-10-06 12:58:14 +02:00
qutebrowser bot 24aab77607 Update dependencies 2025-10-06 04:22:56 +00:00
Florian Bruhin c37b9ebf5b tests: Adjust for changed exception
Follow-up to 2ae3086244
2025-10-02 09:28:55 +02:00
Florian Bruhin 2ae3086244 qutescheme: Improve handling of invalid path -> host redirects 2025-10-02 09:07:15 +02:00
Florian Bruhin 4aa807032f qutescheme: Simplify URL/path normalization logic
See #8711
2025-10-02 09:04:17 +02:00
Florian Bruhin 0867a95abb qutescheme: Add tests for redirects 2025-10-02 08:59:23 +02:00
Florian Bruhin 25ff649efe Fix lint 2025-10-01 17:14:43 +02:00
Florian Bruhin f57afa39e8 webenginetab: Improve _on_navigation_request workarounds
- Use QTimer.singleShot to avoid crashes with QtWebEngine 6.10:
  https://bugreports.qt.io/browse/QTBUG-140543
- Disable back/forward workaround for QtWebEngine >= 6.6,
  as the underlying issue seems to be fixed there.

See https://github.com/qutebrowser/qutebrowser/issues/8694#issuecomment-3276397840
and #8711.
2025-10-01 17:09:01 +02:00
Florian Bruhin da8428f9ba webenginetab: Move QtWebEngine specific workaround
See #8711
2025-10-01 16:31:30 +02:00
Florian Bruhin 75475ee87b version: Adjust security patch version for Qt 6.10 RC 2025-09-30 09:02:07 +02:00
Florian Bruhin 8ebce896ad
Merge pull request #8717 from qutebrowser/update-dependencies
Update dependencies
2025-09-30 09:02:27 +02:00
qutebrowser bot 43b5618c0a Update dependencies 2025-09-29 04:23:12 +00:00
Florian Bruhin c9498995df
Merge pull request #8709 from andyflesner/patch-1
Update Python performance reference link in FAQ
2025-09-24 09:12:28 +02:00
Florian Bruhin aaba038a16
Merge pull request #8708 from qutebrowser/update-dependencies
Update dependencies
2025-09-24 08:00:56 +02:00
Florian Bruhin 92f3633662 tests: Skip nested prompts test on unaffected Qt versions
Qt < 6.9 doesn't crash in this situation, and seems to handle nested prompts
differently, causing the test to still wait for a prompt answer.

Follow-up to a13306a79f
2025-09-24 07:59:21 +02:00
Andy Flesner 7ce0e03614
Update Python performance reference link in FAQ 2025-09-23 21:45:27 -05:00
qutebrowser bot d64781c31c Update dependencies 2025-09-22 04:24:08 +00:00
Florian Bruhin a8f9fc1396 Update changelog 2025-09-21 18:36:36 +02:00
Florian Bruhin a13306a79f Fix exception when quitting with download prompt open
If we have a pending download with a prompt and quit qutebrowser, we get:

    mainwindow:closeEvent:715 Closing window 0
    quitter:shutdown:221 Shutting down with status 0, session None...
    prompt:shutdown:121 Shutting down with loops [<qutebrowser.utils.qtutils.EventLoop object at 0x7fa034725770>]
    quitter:shutdown:235 Deferring shutdown stage 2
    prompt:ask_question:179 Ending loop.exec() for <qutebrowser.utils.usertypes.Question default='/tmp/qbdl/download/' mode=<PromptMode.download: 5> option=None text='Please enter a location for <b>https://proof.ovh.net/files/1Mb.dat</b>' title='Save file to:'>
    prompt:ask_question:181 Restoring old question None
    prompt:_on_show_prompts:299 Deleting old prompt qutebrowser.mainwindow.prompt.DownloadFilenamePrompt(question=<qutebrowser.utils.usertypes.Question default='/tmp/qbdl/download/' mode=<PromptMode.download: 5> option=None text='Please enter a location for <b>https://proof.ovh.net/files/1Mb.dat</b>' title='Save file to:'>)
    prompt:_on_show_prompts:303 No prompts left, hiding prompt container.
    objreg:on_destroyed:112 schedule removal: 0
    objreg:on_destroyed:112 schedule removal: tab
    [...]
    objreg:on_destroyed:112 schedule removal: 0
    objreg:on_destroyed:112 schedule removal: main-window
    objreg:on_destroyed:112 schedule removal: tabbed-browser
    objreg:on_destroyed:112 schedule removal: status-command
    objreg:on_destroyed:112 schedule removal: completion
    objreg:on_destroyed:112 schedule removal: mode-manager
    objreg:on_destroyed:112 schedule removal: hintmanager
    objreg:on_destroyed:112 schedule removal: prompt-container
    quitter:_shutdown_2:241 Stage 2 of shutting down...
    [...]
    webenginedownloads:_on_state_changed:63 State for <qutebrowser.browser.webengine.webenginedownloads.DownloadItem basename='1Mb.dat'> changed to DownloadCancelled
    downloads:_on_begin_remove_row:1076 _on_begin_remove_row with idx 0, webengine True
    downloads:_remove_item:995 Removed download 1: 1Mb.dat [100%|?.??B]
    modeman:leave:429 Leaving mode KeyMode.prompt (reason: aborted)
    crashsignal:_handle_early_exits:229 Uncaught exception
    Traceback (most recent call last):
    File "[...]/qutebrowser/mainwindow/prompt.py", line 344, in _on_aborted
        modeman.leave(self._win_id, key_mode, 'aborted', maybe=True)
        ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "[...]/qutebrowser/keyinput/modeman.py", line 214, in leave
        instance(win_id).leave(mode, reason, maybe=maybe)
        ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "[...]/qutebrowser/keyinput/modeman.py", line 435, in leave
        self.left.emit(mode, self.mode, self._win_id)
        ^^^^^^^^^
    RuntimeError: wrapped C/C++ object of type ModeManager has been deleted
2025-09-21 18:33:05 +02:00
Florian Bruhin c6b486ce81 Fix segfault with nested download prompts
For an unknown reason, if a download prompt is triple-nested, Qt segfaults here:

    #0  add_lazy_attrs (td=0x7ffff52e0dd1 <QtPrivate::sizedFree(void*, unsigned long)+32>) at sip_core.c:6255
    #1  sip_add_all_lazy_attrs (td=0x7ffff52e0dd1 <QtPrivate::sizedFree(void*, unsigned long)+32>) at sip_core.c:6304
    #2  0x00007ffff636598e in sip_api_is_py_method_12_8 (gil=gil@entry=0x7fffffff8b8c, pymc=pymc@entry=0x7fffffff8b8b "", sipSelfp=sipSelfp@entry=0x7fffffff8ba8, cname=cname@entry=0x0, mname=mname@entry=0x7ffff636d57b "__dtor__") at sip_core.c:7402
    #3  0x00007ffff6365c2c in sip_api_is_py_method_12_8 (mname=0x7ffff636d57b "__dtor__", cname=0x0, sipSelfp=0x7fffffff8ba8, pymc=0x7fffffff8b8b "", gil=0x7fffffff8b8c) at sip_core.c:7356
    #4  callPyDtor (self=<optimized out>) at sip_core.c:5375
    #5  sip_api_instance_destroyed_ex (sipSelfp=0x7fffffff8c40) at sip_core.c:5311
    #6  0x00007ffff5fc9967 in sipQEventLoop::~sipQEventLoop() () from [...]/python3.13/site-packages/PyQt6/QtCore.abi3.so
    #7  0x00007ffff0bcd749 in QFileInfoGatherer::getInfo (this=0x5555583f9bc0, fileInfo=...) at [...]/qt5/qtbase/src/gui/itemmodels/qfileinfogatherer.cpp:349
    #8  0x00007ffff0be2629 in QFileSystemModelPrivate::fileSystemChanged (this=0x5555583f9870, path="/tmp/qbdl/download", updates=QList<std::pair<QString, QFileInfo>> (size = 3) = {...}) at [...]/qt5/qtbase/src/gui/itemmodels/qfilesystemmodel.cpp:1966
    (full stacktrace has 183 frames)

After a lot of experimentation, I figured out that moving the `NullIconProvider`
to a class variable (or removing it entirely) seems to help. Note that making it
`global` (but keeping the instanciation inside `FilenamePrompt._init_fileview()`)
did not!

This is semi-blind fix: It's unclear to me if this is a proper fix, or if the
changed memory layout just causes the issue to temporary disappear.

However, given that `QFileInfoGatherer::getInfo()` calls into the icon provider,
it might very well be the real deal.

Closes #8674
2025-09-21 18:07:34 +02:00
Florian Bruhin 18bea32975 Revert "pylint: Remove unneeded suppression"
This reverts commit 7e770765a9.
2025-09-17 18:08:06 +02:00
Florian Bruhin 7e770765a9 pylint: Remove unneeded suppression 2025-09-17 16:06:01 +02:00
Florian Bruhin 1aaf621409 pakjoy: Move main block to function 2025-09-17 15:59:08 +02:00
Florian Bruhin 7d8d14eb07 config: Add file select completions for yazi 2025-09-17 15:44:37 +02:00
Florian Bruhin 226d167ec7 Qt 6.10: Skip incompatible pakjoy tests
See https://github.com/qutebrowser/qutebrowser/issues/8694#issuecomment-3276414407
2025-09-17 15:35:22 +02:00
Florian Bruhin a7822d1e2a pakjoy: Add simple example code 2025-09-16 11:14:47 +02:00
Florian Bruhin 1f4ca40f78 tests: Work around Qt 6.10 permission persistence bug
https://bugreports.qt.io/browse/QTBUG-140194
https://github.com/qutebrowser/qutebrowser/issues/8694#issuecomment-3274635002
2025-09-16 10:58:47 +02:00
Florian Bruhin 75239be8b6 Merge branch 'update-dependencies' 2025-09-15 18:00:46 +02:00
Florian Bruhin 488339b3d5 coverage: Set patch = subprocess
Subprocess measuring got integrated into coverage.py and removed from
pytest-cov:

https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst#700-2025-09-09
https://coverage.readthedocs.io/en/latest/config.html#run-patch
2025-09-15 13:12:38 +02:00
qutebrowser bot 52917f9c31 Update dependencies 2025-09-15 04:21:54 +00:00
Florian Bruhin 326a83309a version: Update for Qt 6.10 Beta 4 2025-09-11 01:00:01 +02:00
Florian Bruhin 264d91eaec ci: Fix shellcheck 2025-09-09 23:27:24 +02:00
Florian Bruhin 9e280eb80f ci: Add scoop dir to PATH 2025-09-09 23:23:07 +02:00
Florian Bruhin c278069946 ci: Fix actionlint 2025-09-09 23:11:03 +02:00
Florian Bruhin 5894221924 ci: Upgrade release workflow to windows 2022
windows-2019 is unsupported by GitHub Actions:
https://github.com/actions/runner-images/issues/12045
2025-09-09 22:07:55 +02:00
Florian Bruhin af2450591c ci: Install NSIS manually for nightly builds
window-latest switched to windows-2025, where GitHub doesn't preinstall NSIS:
https://github.com/actions/runner-images/issues/12677

Let's install it manually (untested, might need follow-up commits).

The release.yml workflow uses windows-2019 (and will switch to windows-2022 in a
follow-up commit), so it is unaffected for now.
2025-09-09 22:07:55 +02:00
Florian Bruhin 65de4fde16 pakjoy: Fix filename for debug builds 2025-09-09 22:07:55 +02:00
Florian Bruhin 4d6dccfed5 Qt 6.10: Ignore new logging messages
See #8694
2025-09-09 22:07:55 +02:00
Florian Bruhin 45483d0994
Merge pull request #8698 from qutebrowser/update-dependencies
Update dependencies
2025-09-08 23:38:42 +02:00
Florian Bruhin c3eef39050
Merge pull request #8701 from qutebrowser/dependabot/github_actions/actions/setup-node-5
build(deps): bump actions/setup-node from 4 to 5
2025-09-08 23:31:04 +02:00
Florian Bruhin a93f2e917d
Merge pull request #8700 from qutebrowser/dependabot/github_actions/actions/github-script-8
build(deps): bump actions/github-script from 7 to 8
2025-09-08 23:30:33 +02:00
Florian Bruhin d8beaa1e9d
Merge pull request #8699 from qutebrowser/dependabot/github_actions/actions/setup-python-6
build(deps): bump actions/setup-python from 5 to 6
2025-09-08 23:30:11 +02:00
dependabot[bot] aa6fcab23a
build(deps): bump actions/setup-node from 4 to 5
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 5.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 19:00:03 +00:00
dependabot[bot] 1e243b0d06
build(deps): bump actions/github-script from 7 to 8
Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 8.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v7...v8)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 18:59:59 +00:00
dependabot[bot] ce6be4f741
build(deps): bump actions/setup-python from 5 to 6
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 18:59:56 +00:00
qutebrowser bot 195d19ec3f Update dependencies 2025-09-08 04:22:17 +00:00
Florian Bruhin 78b55f84cc scripts: Handle ImportError without QUTE_QT_WRAPPER set in link_pyqt
If link_pyqt() is run from mkvenv.py, QUTE_QT_WRAPPER may not be set,
so we shouldn't crash when trying to display import error messages.
2025-09-05 11:24:51 +02:00
Florian Bruhin 7f532f69d2 requirements: Qt 6.9.2 2025-09-03 00:38:32 +02:00
Florian Bruhin 50080e8607
Merge pull request #8692 from qutebrowser/update-dependencies
Update dependencies
2025-09-03 00:31:42 +02:00
Florian Bruhin 17522478db version: Update for QtWebEngine 6.9.2 and 6.10 2025-09-02 23:47:00 +02:00
qutebrowser bot 44dbef482e Update dependencies 2025-09-01 04:26:18 +00:00
Florian Bruhin c0216a1309 Update changelog 2025-08-25 10:27:11 +02:00
Florian Bruhin c63a98e3e6 Merge remote-tracking branch 'origin/pr/8681' 2025-08-25 10:26:38 +02:00
Florian Bruhin 08f5509bed Fix tests with broken asciidoc install 2025-08-25 10:26:25 +02:00
Florian Bruhin 4180e04f24
Merge pull request #8686 from qutebrowser/update-dependencies
Update dependencies
2025-08-25 09:07:41 +02:00
qutebrowser bot 3cdacde13e Update dependencies 2025-08-25 04:23:50 +00:00
Sander ada069b3e3
feat(qutedmenu): sort history results by last access time 2025-08-21 23:20:34 +02:00
Florian Bruhin 9e99d6df34
Merge pull request #8676 from qutebrowser/update-dependencies
Update dependencies
2025-08-18 23:08:52 +02:00
qutebrowser bot afd1515d8d Update dependencies 2025-08-18 04:33:54 +00:00
Florian Bruhin 6d1cd0282a
Merge pull request #8670 from qutebrowser/update-dependencies
Update dependencies
2025-08-14 00:52:36 +02:00
Florian Bruhin 21082a85a4
Merge pull request #8673 from qutebrowser/dependabot/github_actions/actions/checkout-5
build(deps): bump actions/checkout from 4 to 5
2025-08-14 00:50:12 +02:00
dependabot[bot] 745bb7f4f0
build(deps): bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 01:09:55 +00:00
qutebrowser bot ec86816be1 Update dependencies 2025-08-11 04:37:07 +00:00
Florian Bruhin 85e1a132bb scripts: Update shellcheck error ignores for password_fill 2025-08-04 11:35:04 +02:00
Florian Bruhin d8fd61811c
Merge pull request #8659 from qutebrowser/update-dependencies
Update dependencies
2025-08-04 10:14:55 +02:00
qutebrowser bot 40b3e70659 Update dependencies 2025-08-04 04:43:36 +00:00
Florian Bruhin 0c035c41d8 Adjust qt.workarounds.disable_accelerated_2d_canvas description
Closes #8660
2025-07-29 10:15:06 +02:00
Florian Bruhin f2ec540a1b tests: Fix sys.flags workaround with older Python versions
types.SimpleNamespace only accepts a positional argument with Python 3.13: 'https://docs.python.org/3/whatsnew/3.13.html#types'
2025-07-29 10:10:13 +02:00
Florian Bruhin b9aec6777a tests: Fix monkeypatching of sys.flags on Python 3.14
With Python 3.14, since argparse enabled coloring by default:
17c5959aa3
running test_cmdutils.py failed with a lengthy traceback finishing in:

```
INTERNALERROR> pluggy.PluggyTeardownRaisedWarning: A plugin raised an exception during an old-style hookwrapper teardown.
INTERNALERROR> Plugin: /home/florian/proj/qutebrowser/git/tests/conftest.py, Hook: pytest_runtest_makereport
INTERNALERROR> PluggyTeardownRaisedWarning: A plugin raised an exception during an old-style hookwrapper teardown.
INTERNALERROR> Plugin: rerunfailures, Hook: pytest_runtest_makereport
INTERNALERROR> PluggyTeardownRaisedWarning: A plugin raised an exception during an old-style hookwrapper teardown.
INTERNALERROR> Plugin: hypothesispytest, Hook: pytest_runtest_makereport
INTERNALERROR> PluggyTeardownRaisedWarning: A plugin raised an exception during an old-style hookwrapper teardown.
INTERNALERROR> Plugin: pytest-bdd, Hook: pytest_runtest_makereport
INTERNALERROR> AttributeError: 'types.SimpleNamespace' object has no attribute 'verbose'
```

with one part pointing to Python internals:

```pytb
INTERNALERROR>   File "/home/florian/proj/qutebrowser/git/.tox/py314-pyqt68/lib/python3.14/site-packages/_pytest/_code/code.py", line 669, in exconly
INTERNALERROR>     lines = format_exception_only(self.type, self.value)
INTERNALERROR>   File "/usr/lib/python3.14/traceback.py", line 180, in format_exception_only
INTERNALERROR>     te = TracebackException(type(value), value, None, compact=True)
INTERNALERROR>   File "/usr/lib/python3.14/traceback.py", line 1106, in __init__
INTERNALERROR>     suggestion = _compute_suggestion_error(exc_value, exc_traceback, wrong_name)
INTERNALERROR>   File "/usr/lib/python3.14/traceback.py", line 1653, in _compute_suggestion_error
INTERNALERROR>     import _suggestions
INTERNALERROR>   File "<frozen importlib._bootstrap>", line 1371, in _find_and_load
INTERNALERROR>   File "<frozen importlib._bootstrap>", line 1342, in _find_and_load_unlocked
INTERNALERROR>   File "<frozen importlib._bootstrap>", line 951, in _load_unlocked
INTERNALERROR>   File "<frozen importlib._bootstrap>", line 496, in _verbose_message
INTERNALERROR> AttributeError: 'types.SimpleNamespace' object has no attribute 'verbose'
```

This happens when Python tries to access sys.flags.verbose, but we replaced it
with a fake object that does not have a .verbose attribute anymore (only
temporarily, but for some reason that's enough to trigger the issue anyways).

Since we can't mutate sys.flags, instead we create an object that copies all
sys.flags attributes, and then use that as a nicer replacement.

See #8529
2025-07-27 13:58:15 +02:00
Florian Bruhin 6b3b83981a Qt 6.10: Adjust security patch version 2025-07-21 13:47:45 +02:00
Florian Bruhin d80d80b867 Qt 6.10: Adjust CI test skipping 2025-07-21 13:47:45 +02:00
Florian Bruhin c9d3b61ca2
Merge pull request #8656 from qutebrowser/update-dependencies
Update dependencies
2025-07-21 13:42:03 +02:00
qutebrowser bot 87ad9dce57 Update dependencies 2025-07-21 04:37:45 +00:00
Florian Bruhin 961b4a212d
Merge pull request #8644 from qutebrowser/update-dependencies
Update dependencies
2025-07-14 07:27:52 +02:00
qutebrowser bot e151c2d0cf Update dependencies 2025-07-14 04:34:13 +00:00
Florian Bruhin c79257dc8d Remove pytest-mock pytest warning ignore
Fixed in pytest-mock 3.14.1
2025-07-08 21:15:15 +02:00
Florian Bruhin 22f1b57347 lint: Move check-manifest into pyroma
pyroma now runs check-manifest if installed,
so we can simplify things there.
2025-07-07 08:09:47 +02:00
Florian Bruhin 2536cc2313 tox: Fail pyroma run on degradations
The only rating we're satisfied with is Mascarpone!
2025-07-07 08:04:25 +02:00
Florian Bruhin d15052a67a Add stub pyproject.toml file
This keeps our setup.py around for now, while still supporting a PEP-517
compliant build. It's the minimum required change to make modern pyroma stop
complaining, and hopefully to avoid deprecation warnings.

Partially duplicates #8560
See #3526
2025-07-07 08:00:29 +02:00
qutebrowser bot be87927923 Update dependencies 2025-07-07 04:27:56 +00:00
Florian Bruhin 7315c34957 Add support for hinting elements inside shadow DOMs
Supersedes and closes #7617
See #3569 (fixed partially)
2025-07-01 16:49:10 +02:00
Florian Bruhin 8bf6a9c448
Merge pull request #8629 from qutebrowser/update-dependencies
Update dependencies
2025-06-30 08:04:38 +02:00
qutebrowser bot 9e459a004c Update dependencies 2025-06-30 04:28:14 +00:00
Florian Bruhin e7af54898e Add X11/Wayland information to version info
Unfortunately there is no way to get this information from Qt, so I had to
resort to some funny low-level C-like Python programming to directly use
libwayland-client and Xlib. Fun was had! Hopefully this avoids having to ask
for this information every time someone shows a bug/crash report, as there
are various subtleties that can be specific to the Wayland compositor in use.
2025-06-25 09:34:35 +02:00
Florian Bruhin 7664fdbb34
Merge pull request #8623 from qutebrowser/update-dependencies
Update dependencies
2025-06-24 20:53:48 +02:00
Florian Bruhin 81546c97ae version: Add security patch level for QtWebEngine 6.10 Beta 1 2025-06-24 20:42:03 +02:00
qutebrowser bot b2f58856a8 Update dependencies 2025-06-23 04:29:58 +00:00
Florian Bruhin 5e565f4dc7 Fix PermissionElement tests 2025-06-16 22:27:55 +02:00
Florian Bruhin 879c964c35 Update changelog 2025-06-16 14:09:41 +02:00
Florian Bruhin 2ec0f8fa77 Extend PermissionElement workaround to Qt 6.9.1+
Fixes #8612
2025-06-16 14:09:41 +02:00
Florian Bruhin 9d5aeefa8c
Merge pull request #8610 from qutebrowser/update-dependencies
Update dependencies
2025-06-16 10:33:39 +02:00
qutebrowser bot ed6329737f Update dependencies 2025-06-16 04:28:21 +00:00
Florian Bruhin 04a1d11905
Merge pull request #8603 from qutebrowser/update-dependencies
Update dependencies
2025-06-09 10:47:18 +02:00
qutebrowser bot 47724f913e Update dependencies 2025-06-09 04:26:50 +00:00
Florian Bruhin a45d57feee tests: Adjust ignored log message for newer Chromium
QtWebEngine 6.9 seems to use webengine/DawnWebGPUCache/ instead of DawnCache/
2025-06-06 12:53:10 +02:00
Florian Bruhin eca17870ae tests: Extend Qt 6.9.0 workaround to .1
Still seems to be failing, see https://github.com/qutebrowser/qutebrowser/issues/8444#issuecomment-2569610110
2025-06-06 11:30:27 +02:00
Florian Bruhin 959dc5a9e5 tests: Correctly deactivate SignalHandler after tests
Otherwise, the python_hacks timer might continue running
and affects test_early_timeout_check, similiarly to what was fixed in
74c7ff2641.
2025-06-06 10:53:38 +02:00
Florian Bruhin 7b388017c3 Update changelog 2025-06-06 08:51:00 +02:00
Florian Bruhin 55ca67f3e2 tests: Stop hardcoding indices for module versions 2025-06-06 08:49:28 +02:00
Florian Bruhin 6b86a9072f version: Rely on importlib.metadata.version too
Packages are slowly migrating to not having a __version__ attribute anymore,
instead relying on importlib.metadata to query the installed version.

jinja2 now shows a deprecation warning when accessing the __version__
attribute: https://github.com/pallets/jinja/pull/2098

For now we keep accessing __version__ for other packages (we still need the
logic for PyQt and its special version attributes anyways), but we fall back on
importlib.metadata.version if we can't get a version that way, and we stop
trying __version__ for jinja2.
2025-06-06 08:47:00 +02:00
qutebrowser bot 96e535c7ed Release v3.5.1
(cherry picked from commit be7cf1ab15)
2025-06-05 14:55:03 +00:00
Florian Bruhin 1217f7fa45 Update user agents 2025-06-05 16:38:10 +02:00
Florian Bruhin c1e7b6e8f3 tests: Ignore test_restart hang on Windows 2025-06-05 15:09:57 +02:00
Florian Bruhin 2e343403de tests: Ignore another bogus Chromium log message 2025-06-05 15:08:00 +02:00
Florian Bruhin 2ec16a947f ci: Switch nightly builds to windows-latest
We don't really care which exact Windows version we use there
2025-06-05 15:01:29 +02:00
Florian Bruhin ced24549df Update changelog 2025-06-05 14:22:40 +02:00
Florian Bruhin 272693ef3e Adjust comment 2025-06-05 14:06:43 +02:00
Florian Bruhin 5926932a6d Update changelog 2025-06-05 14:06:03 +02:00
Florian Bruhin 3f31a0005a Fix mimetype for PDF.js files on Windows
With windows-2022 and windows-2025 on GitHub Actions,
we get:

    qutescheme:data_for_url:128 url: qute://pdfjs/web/viewer.mjs, path: /web/viewer.mjs, host pdfjs
    webenginequtescheme:requestStarted:105 Returning text/plain data

which causes:

    JS: [qute://pdfjs/build/pdf.mjs:0] Failed to load module script: Expected a
    JavaScript module script but the server responded with a MIME type of
    "text/plain". Strict MIME type checking is enforced for module scripts per
    HTML spec.

It's unclear why we get text/plain back there in the first place (can't
reproduce on a local Windows 11 install), but it's definitely wrong, so let's
just override that problematic case.
2025-06-05 13:41:28 +02:00
Florian Bruhin 9219869cb9 ci: Test on windows-2022 and windows-2025
windows-2019 is deprecated: https://github.com/actions/runner-images/issues/12045
2025-06-05 11:38:42 +02:00
Florian Bruhin 0b5f70f029 ci: Switch to Qt 6.9 for Windows/macOS
That's what we're shipping, so we should also test that.
2025-06-05 11:36:33 +02:00
Florian Bruhin bff2ad9086 version: Add QtWebEngine 6.9.1 2025-06-05 11:33:41 +02:00
Florian Bruhin 696a4490ff Hide Qt 6.9.1 IPC signal warning
The warning is triggered from inside Qt and most
likely bogus:
https://bugreports.qt.io/browse/QTBUG-137424

See https://github.com/qutebrowser/qutebrowser/pull/8595#issuecomment-2938912511
2025-06-05 11:17:35 +02:00
qutebrowser bot 9cf95165a9 Update dependencies 2025-06-04 06:44:58 +00:00
toofar f9eb71b4c8
Merge pull request #8593 from qutebrowser/update-dependencies
Update dependencies
2025-06-03 21:39:42 +12:00
toofar 422680046e Update PDF.js version extraction for 5.3.31
It's changed in this PR: https://github.com/mozilla/pdf.js/pull/19956
to have the version string as a comment in the file, instead of the
variable.

Making the regex more forgiving increases the chance of matching on the
wrong string on a past or future version. I've only tested with the
previous version (v5.2.133) and it seemed to still work there.

Changes I made to the regex:

* add the literal * to the match group of possible prefixes of pdfjsVersion
* make the quotes around the version optional
* make the semicolon at the end of the line optional
* add newline to the list of characters that can terminate the match
  group (otherwise it was matching across the end of the line up to the
  first string, kinda odd when there was a $ after the match group)
2025-06-02 20:51:30 +12:00
toofar 060f4a59d6 mypy: cast variable only on Qt5
We only have to cast these variables on Qt5. If we cast them on Qt6 mypy
warns of a redundant cast. If we ignore that warning mypy complains of a
redundant ignore on Qt5.

Add a conditional on `machinery.IS_QT5` and only cast it required.

But also move that conditional out to a utility function to avoid
duplicating code in the function doing the actual logic.

I'm re-using the `_T` generic TypeVar defined above. Not sure if it's
proper to re-use them or not. Doesn't python have a better way of
defining generics now?

I added the `valid-type` ignore because mypy was complaining:

    Variable "to_type" is not valid as a type

I'm not sure if there is some way to do it better, but `reveal_type()`
says that the call site is getting the right type back in the end.
2025-06-02 20:03:00 +12:00
qutebrowser bot 291dda69e5 Update dependencies 2025-06-02 04:26:41 +00:00
Florian Bruhin 329977b42c
Merge pull request #8587 from qutebrowser/update-dependencies
Update dependencies
2025-05-30 12:27:00 +02:00
Florian Bruhin 072b03a631 Avoid version warnings with PyQtWebEngine-Qt5 5.15.17
With PyQtWebEngine-Qt5 5.15.17 (Qt 5.15.19), we seem to run into similar issues
like we already did with Qt 6.5:

https://github.com/qutebrowser/qutebrowser/issues/7624#issuecomment-1474008470
9cb54b2099

However, skipping the ELF test is not enough, as we also get warnings
at runtime (as we don't have any API to get the version at runtime).

We don't care much about Qt 5 at this stage, so let's just not output
warnings in that case (and nothing in the code should care about the exact
QtWebEngine patch level beyond 5.15.2 anyways).

For most user-facing things, we *can* get the exact version number from
the user-agent, so this should not actually affect much.
2025-05-29 23:42:40 +02:00
Florian Bruhin 9ba931075b doc: Add Doom-One theme 2025-05-26 17:46:07 +02:00
qutebrowser bot 0de8337969 Update dependencies 2025-05-26 04:25:50 +00:00
Florian Bruhin aef5355436 Revert "flake8: Disable N808"
This reverts commit a14b986326.

Now allowed in pep8-naming 0.15.1.
2025-05-19 16:05:46 +02:00
Florian Bruhin 856aeb3f47 Avoid log spam on new QWebEngineView children
With Qt 6.9, Qt creates QObjects for accessibility
tree nodes, which result in a lot of log spam.

Fixes #8542
2025-05-19 16:04:58 +02:00
Florian Bruhin c86ddd11be
Merge pull request #8579 from qutebrowser/update-dependencies
Update dependencies
2025-05-19 10:20:20 +02:00
qutebrowser bot aab33cc596 Update dependencies 2025-05-19 04:24:12 +00:00
Florian Bruhin bb7bbb6ead eventfilter: Ignore QKeyEvents in ChildEventFilter
Based on crash reports, sometimes somehow a QKeyEvent gets lost in there.
2025-05-16 18:17:44 +02:00
Florian Bruhin 9447182809 Add debug logging for failed WebEngineHistory deserialization
This sometimes fails with 'The data stream has read past the end of the data in
the underlying device', which turns up in crash reports around once a month.

This is somewhat similar to https://bugreports.qt.io/browse/QTBUG-117489 - but
without knowing the data and without being able to reproduce, it's unclear what
the culprit could be.
2025-05-14 08:47:08 +02:00
Florian Bruhin 9c7a75616c ci: Switch to tox main branch 2025-05-13 12:32:02 +02:00
Florian Bruhin 858606c18d ci: Remove QtWebKit testing
It's broken in weird ways since recently (`:version` not loading,
segfault in test_version.py). Since nobody should be using it anyways,
there is no point in spending time on debugging a tricky issue.

Next step is probably ripping it out completely, but that's a separate
can of worms.

See #4039
2025-05-13 09:29:04 +02:00
Florian Bruhin 049cf49705
Merge pull request #8567 from qutebrowser/update-dependencies
Update dependencies
2025-05-13 09:25:35 +02:00
qutebrowser bot 4633a0704e Update dependencies 2025-05-12 04:22:23 +00:00
Florian Bruhin a2072db15d requirements: use full syntax for misc checks 2025-05-08 11:25:14 +02:00
Florian Bruhin 9685c5a383 requirements: Use patched tox for Python 3.14
See https://github.com/tox-dev/tox/issues/3523
2025-05-08 11:22:55 +02:00
Florian Bruhin c682ccb1b2 tests: Ignore more libEGL warnings 2025-05-08 10:17:03 +02:00
Florian Bruhin 81f65dbb46 docker: Install libxml2-legacy from official repos
Reverts:
- a3bdcca37b
- 1b7557b73b
- 06e7950588
- 9aef02e96c
- c5fe31e828
2025-05-08 09:21:35 +02:00
Florian Bruhin 6cbf2847c8 docker: Try working around QtWebKit issues 2025-05-07 17:59:15 +02:00
Florian Bruhin 74c7ff2641 tests: Properly delete webengine DownloadManager objects
We create the DownloadManager with parent=qapp, which means they will stick
around forever after the test finished.

While we disconnect the QWebEngineProfile::downloadRequested() signal,
we keep the DownloadManager around, which also keeps around its download-update
timers.

Those will then result in tests/unit/utils/usertypes/test_timer.py::test_early_timeout_check
being flaky, as their _validity_check_handler slot keeps getting called in the
background. Due to the globally mocked time.monotonic(), this results in
nonsensical error messages such as:

    Got logging message on logger misc with level WARNING:
    Timer download-update (id ...) triggered too early:
    interval 500 but only -1023.269s passed!

After this change, we now clean up those objects properly, thus fixing the
flakiness.

See #5390.
2025-05-07 14:06:03 +02:00
Florian Bruhin a4b3ca48df tests: Add sanity check for stray timer objects
This makes sure the test consistently fails if there is still some timer in the
background, instead of getting flaky.
2025-05-07 13:39:48 +02:00
Florian Bruhin 9f16a1f879 tests: Properly delete mode_manager instances
To fix a flaky tests/unit/utils/usertypes/test_timer.py::test_early_timeout_check
(where a download-update timer from an earlier test fails), I looked into what
usertypes.Timer instances where left over after a test finished.

It turns out that there were about 190 still existing "partial-match" and
"normal-inhibited" timers when breaking in test_timer.py, even when just running
tests in tests/unit/browser/ and tests/unit/utils/usertypes.

This is because we pass qapp as parent to the ModeManager we create, but that
means it will be forever alive if we don't take care of cleaning it up after a
test.

Perhaps our tests should have some sort of mechanism that checks whether there
are any "leftovers" after a test has finished (perhaps even as part of
pytest-qt?), but for now, let's just fix the issues we can directly see.
2025-05-07 13:22:10 +02:00
Florian Bruhin ed99c82440 tests: Fix pattern 2025-05-06 14:41:13 +02:00
Florian Bruhin 20a9130cee Ignore a random Qt 5 log message
No idea where this came from...
2025-05-06 14:27:57 +02:00
Florian Bruhin 102f43cbde scripts: Ignore another stderr output on macOS 2025-05-06 14:08:00 +02:00
Florian Bruhin c5fe31e828 docker: Add link 2025-05-06 14:06:10 +02:00
Florian Bruhin 9aef02e96c docker: Don't install libxml2.13 for webkit 2025-05-06 10:28:17 +02:00
Florian Bruhin 06e7950588 docker: Always install base-devel 2025-05-06 09:18:07 +02:00
Florian Bruhin 1b7557b73b docker: Don't run makepkg as root 2025-05-06 09:15:27 +02:00
Florian Bruhin 5e6a878f64 docker: Also downgrade libarchive for QtWebEngine 2025-05-06 09:12:23 +02:00
Florian Bruhin a3bdcca37b docker: Install libxml2.13 2025-05-06 09:11:20 +02:00
Florian Bruhin 0a9b6aab73 debug: Make get_all_objects usable without objects.qapp
Needed for some test debugging, and seems harmless enough to just commit as-is
as I might need it again.
2025-05-05 09:53:06 +02:00
Florian Bruhin 8f8748e486
Merge pull request #8558 from qutebrowser/update-dependencies
Update dependencies
2025-05-05 08:46:09 +02:00
Florian Bruhin a14b986326 flake8: Disable N808 2025-05-05 08:15:52 +02:00
qutebrowser bot 422d268fe3 Update dependencies 2025-05-05 04:21:54 +00:00
toofar b3138d1be8
Merge pull request #8553 from qutebrowser/update-dependencies
Update dependencies
2025-04-25 18:36:08 +12:00
toofar e67aea60e8 Update changelog link for mypy extensions 2025-04-25 16:50:07 +12:00
toofar 67e7677523 Downgrade hypothesis
Skip this hypothesis version pending https://github.com/HypothesisWorks/hypothesis/issues/4375
Our test suite is currently failing due to running python with `-b` and
being configured to fail on warnings.

We'll pick it up on the next update run or so.
2025-04-25 16:47:01 +12:00
qutebrowser bot 9249c5cb0e Update dependencies 2025-04-25 04:33:28 +00:00
Florian Bruhin c601bd0c7a
Merge pull request #8545 from qutebrowser/update-dependencies
Update dependencies
2025-04-17 11:19:31 +02:00
Florian Bruhin f9933d2f3e userscripts: Properly avoid tldextract warning
The previous fix in 3dc212a815 was insufficient,
as the inner `getattr(extract_result, "registered_domain")` was always evaluated
first (thus triggering the deprecation warning again).

We also cannot do:

    getattr(extract_result, "top_domain_under_public_suffix", None) or extract_result.registered_domain

as `""` is a valid value for it.
2025-04-17 11:11:33 +02:00
qutebrowser bot 95f9472a6b Update dependencies 2025-04-14 04:21:48 +00:00
toofar 701046cd9f
Merge pull request #8537 from qutebrowser/update-dependencies
Update dependencies
2025-04-14 12:08:02 +12:00
Florian Bruhin aa41b6719f tests: Ignore another message 2025-04-13 14:53:21 +02:00
Florian Bruhin 05b42c57ee ci: Fix config properly... 2025-04-13 13:40:37 +02:00
Florian Bruhin 77b5c0c1cd ci: Fix config 2025-04-13 13:37:44 +02:00
Florian Bruhin 84ec45c13f ci: Try Python 3.14 again
Cache is now cleared, so it might just work
2025-04-13 13:28:34 +02:00
Florian Bruhin ecbca59dea Update changelog 2025-04-13 10:25:43 +02:00
qutebrowser bot 67d8e012a3 Release v3.5.0 2025-04-12 21:28:50 +00:00
Florian Bruhin dea1de5dab Update changelog 2025-04-12 21:33:19 +02:00
Florian Bruhin 9aa53ea205 tests: Wait for tab-close being run properly
Leaks into the next test otherwise, making it flaky.
2025-04-12 21:28:30 +02:00
Florian Bruhin 7bc6c33bb5 Reapply "tests: Try to stabilize test_auto_leave_insert_mode"
This reverts commit 1d2faf2fa2.

This seems to be correct, the issue is the previous test not waiting until it's
finished properly.
2025-04-12 21:25:11 +02:00
Florian Bruhin 9e0f7ccc51 tests: Make sure we don't leave stale download managers behind
Speculative fix for test_early_timeout_handler in
tests/unit/utils/usertypes/test_timer.py failing:

    >  assert len(caplog.messages) == 1
    E  AssertionError: assert 5 == 1

due to:

    ------------------------------ Captured log call -------------------------------
    WARNING  misc:usertypes.py:467 Timer download-update (id 620757000) triggered too early: interval 500 but only -609.805s passed
    WARNING  misc:usertypes.py:467 Timer download-update (id 922746881) triggered too early: interval 500 but only -609.429s passed
    WARNING  misc:usertypes.py:467 Timer download-update (id 1056964613) triggered too early: interval 500 but only -609.537s passed
    WARNING  misc:usertypes.py:467 Timer download-update (id 1912602631) triggered too early: interval 500 but only -609.671s passed
    WARNING  misc:usertypes.py:467 Timer t (id -1) triggered too early: interval 3 but only 0.001s passed
2025-04-12 21:16:30 +02:00
Florian Bruhin 1d2faf2fa2 Revert "tests: Try to stabilize test_auto_leave_insert_mode"
This reverts commit f6f2a1252b.

Does more harm than good, for reasons I don't entirely understand yet.
2025-04-11 19:45:41 +02:00
Florian Bruhin f6f2a1252b tests: Try to stabilize test_auto_leave_insert_mode
We sometimes tried to use hints before the page was fully rendered (?), thus
causing no elements to be found.

It also doesn't make much sense to test leaving insert mode if we aren't in
insert mode yet, so make sure we entered it first.

See #5390
2025-04-11 17:28:31 +02:00
Florian Bruhin 86c89e00c5 Qt 6.9: Skip more qutescheme tests
If the renderer process crash happens, rerunning
doesn't seem to fix anything, even if the page is
opened in a new tab.

See #8536
2025-04-11 17:18:51 +02:00
Florian Bruhin 4f4ad4147a Revert "tests: Try to combat Qt 6.9 flakiness more"
This reverts commit 7204168684.

Doesn't actually help on CI...
2025-04-11 17:18:32 +02:00
Florian Bruhin 13b87e5968 ci: Avoid Python 3.14 Alpha 7
See https://www.riverbankcomputing.com/pipermail/pyqt/2025-April/046210.html and #8529
2025-04-11 17:18:06 +02:00
Florian Bruhin 7204168684 tests: Try to combat Qt 6.9 flakiness more
See #8536
2025-04-11 16:00:45 +02:00
Florian Bruhin 3dc212a815 userscripts: Avoid tldextract warning 2025-04-11 15:41:59 +02:00
Florian Bruhin 351fef8c1e Update comment 2025-04-10 15:52:50 +02:00
Florian Bruhin 4053249229 tests: Fix deprecated usage 2025-04-08 21:11:43 +02:00
Florian Bruhin 8b820f015b ci/tox/requirements: Update for Qt 6.9 2025-04-08 21:09:32 +02:00
Florian Bruhin afeb1ebbaa tests: Fix TestYamlMigrations.test_user_agent 2025-04-08 20:50:13 +02:00
Florian Bruhin 6b5ebe7187 Add a test for js_async crash
Follow-up to c32f5afcc4
See #3895 and #8400.
2025-04-08 20:47:54 +02:00
Florian Bruhin c073a30afe Update changelog 2025-04-08 20:38:50 +02:00
Florian Bruhin b16551548f Remove QtWebEngine/... from default UA
Good old https://webaim.org/blog/user-agent-string-history/ strikes yet again.
Let's just masquerade as Chromium instead of the constant pointless fight.
2025-04-08 20:28:15 +02:00
Florian Bruhin 961a9390da Remove the ua-slack site specific quirk
Closes #8510
2025-04-08 20:19:34 +02:00
Florian Bruhin b5a399831b tests: Disable MAP_DISCARD workaround for fixed Qt versions 2025-04-08 19:42:16 +02:00
Florian Bruhin bbdf9faf5e Qt 6.9: Mark one more test as flaky 2025-04-08 14:37:51 +02:00
Florian Bruhin d9d8701696 Fix flake8 2025-04-08 14:36:34 +02:00
Florian Bruhin 3280c8dacc tests: Avoid CI issues with qutescheme and Qt 6.9
see #8536
2025-04-08 14:03:26 +02:00
Florian Bruhin 54b6c92713 Python 3.14: Skip newly added stdlib file test
See #8529
2025-04-08 12:35:51 +02:00
Florian Bruhin de3fa06eff Fix lint
mccabe complexity too high, but despite a lot of 'if' the function is quite linear.
2025-04-08 10:42:42 +02:00
Florian Bruhin ef2ceccd29 Qt 6.9: Work around QtWebEngine not handling <permission> element
See #8539
2025-04-07 21:58:45 +02:00
qutebrowser bot 9a23ce6c3c Update dependencies 2025-04-07 04:20:42 +00:00
Florian Bruhin 21b2d63f4d doc: Remove dead matrix bridge link 2025-04-06 14:35:58 +02:00
toofar c32f5afcc4 Fix crash when JS is run async on deleted tabs
My reproducer is this:

* open the browser with the auto insert mode JS primed, and two tabs:

    `python3 -m qutebrowser -T -s input.insert_mode.auto_load true about:blank?1 about:blank?2`

* close the second tab: `d`
* re-open the closed tab then close it again real quick: `u` then `d`

If you have trouble reproducing, try increasing the 65ms delay in
`handle_auto_insert_mode` to be bigger (like 500ms).

Closes: #3895
2025-04-05 18:18:10 +13:00
Florian Bruhin ab3b77cb1e Revert "Make private browsing asserts more useful"
This reverts commit b09a1385f5.
2025-04-04 12:55:28 +02:00
Florian Bruhin b09a1385f5 Make private browsing asserts more useful
The assert in commands.py sometimes fails, hopefully this will help track things down.
2025-04-04 12:02:42 +02:00
Florian Bruhin 4e5eb90857 ci: Fix Python 3.14 Pillow build 2025-04-02 13:34:27 +02:00
Florian Bruhin 72647298b7 ci: Fix Python 3.14 derp 2025-04-02 13:31:55 +02:00
Florian Bruhin 71381c0da6 ci: Try to fix Python 3.14 version 2025-04-02 13:30:46 +02:00
Florian Bruhin 3aa839998b Python 3.14: Add to tox/CI
Part of #8529
2025-04-02 13:22:35 +02:00
Florian Bruhin 65a3a3cf9a Python 3.14: Ignore DeprecationWarnings in plugins
https://github.com/pytest-dev/pytest-mock/issues/468
https://github.com/ionelmc/pytest-benchmark/issues/283

Part of #8529
2025-04-02 13:15:32 +02:00
Florian Bruhin 163bb9fa0c Python 3.14: Update cheroot workaround
https://github.com/cherrypy/cheroot/issues/734
https://github.com/python/cpython/issues/129354
Part of #8529
2025-04-02 12:52:24 +02:00
Florian Bruhin c165d1a0da Update changelog 2025-03-31 13:40:22 +02:00
Florian Bruhin 1ab93bad33
Merge pull request #8329 from VitoMinheere/7966-tab-move-zero-division-error
Fix zero division bug in tab-move +
2025-03-31 13:39:35 +02:00
Florian Bruhin 69f0eae600 Drop unneeded nonlocal 2025-03-31 08:44:45 +02:00
Florian Bruhin ef397e9417 Update changelog URLs 2025-03-31 08:40:01 +02:00
qutebrowser bot c60ebe8eef Update dependencies 2025-03-31 04:21:42 +00:00
Florian Bruhin 4dde8e1594 version: Add security patch version for Qt 6.8.3 2025-03-26 13:51:52 +01:00
Florian Bruhin b6d5a5cf14 Fix and simplify JS quirks tests 2025-03-25 14:23:48 +01:00
Florian Bruhin c4d8502872 Add site-specific quirk for Digitec/Galaxus madness 2025-03-25 13:04:26 +01:00
Florian Bruhin 2f20e3b60b Update iniconfig changelog url 2025-03-24 11:29:35 +01:00
qutebrowser bot 873b874c5f Update dependencies 2025-03-24 11:29:28 +01:00
Florian Bruhin a460770414 tests: Adjust qt69_ci_flaky 2025-03-21 11:29:32 +01:00
Florian Bruhin e4ab45e3b2 setup: Move from deprecated license classifier to SPDX 2025-03-21 11:25:45 +01:00
Florian Bruhin d0407852f4 Fix lint 2025-03-21 11:24:24 +01:00
Florian Bruhin 59be37007d Polyfill URL.parse for PDF.js v5 modern build 2025-03-21 10:42:55 +01:00
Florian Bruhin b43c79989e pdfjs: Add new no-system-pdfjs debug flag
This can be used to easily test a different PDF.js version manually (which is
installed via update_3rdparty.py), without having to uninstall the system-wide
one first.
2025-03-21 10:42:17 +01:00
Florian Bruhin 939e0fa817 Adjust Slack UA quirk
See #8510
2025-03-21 10:42:17 +01:00
toofar 18db4cc937 changelog entries for bitwarden userscript
Will it be cherry picked to the release branch? Should I have made a new
section for the 3.5.0 release? We'll see!
2025-03-19 20:24:10 +13:00
toofar 4a675115e1
Merge pull request #7781 from dezeroku/cleaned-up
userscripts: fix qute-bitwarden failing with expired session
2025-03-19 20:13:13 +13:00
toofar 02b9f5eed1
Merge pull request #8518 from qutebrowser/update-dependencies
Update dependencies
2025-03-18 21:10:16 +13:00
qutebrowser bot cc20112a67 Update dependencies 2025-03-17 04:20:14 +00:00
dezeroku d49c96aa29
userscripts: fix qute-bitwarden failing with expired session
This could be seen as "Vault is locked" error in the logs,
if run with the --nointeraction flag
2025-03-16 16:47:08 +01:00
Florian Bruhin b0e05ee160 Qt 6.9: Only disable software rendering for darkmode tests
Looks like the "tests hanging" issue was fixed between Beta 3 and RC.

See #8444
2025-03-15 16:49:43 +01:00
Florian Bruhin 4c9e989c39 Qt 6.9: Upgrade security patch version 2025-03-15 12:28:55 +01:00
Florian Bruhin 237e90985d docker: Downgrade libxslt
ImportError: /usr/lib/libxslt.so.1: undefined symbol: xmlCtxtParseDocument
2025-03-15 12:25:43 +01:00
Florian Bruhin e3db31e29e tests: Match message properly for invalid URL
pytest now warns about it, which fails bleeding tests:
2c8cd64d5f
2025-03-15 12:25:43 +01:00
user202729 f25604b819 Bitwarden: Pass master password in environment variable 2025-03-12 15:53:50 +01:00
Harm te Molder b183e6a39a Add Solarized theme 2025-03-12 15:52:18 +01:00
Florian Bruhin 1f90da7694 Update user agents / quirks
Fixes #8492 (hopefully)
2025-03-12 15:41:54 +01:00
Florian Bruhin 7ad4bb70fe Shorten Chromium version in UA by default
Fixes #8426
2025-03-12 15:25:55 +01:00
Florian Bruhin b271559f82 tests: Fix without explicit platform 2025-03-12 15:02:22 +01:00
Florian Bruhin 51541add20 Fix lint 2025-03-12 14:44:19 +01:00
Florian Bruhin 328b5966ef Add initial support for running tests offscreen
Makes

    QT_QPA_PLATFORM=offscreen pytest

pass.

See #4914
2025-03-12 14:41:50 +01:00
Florian Bruhin 4cc67d3603 Qt 6.9: Force software rendering for tests
Not yet quite sure what exactly is the culprit, but this seems to help for all
tests (!) to pass with Xvfb locally.

For now only scoped to Qt 6.9.0. Will probably already need to reevaluate with
the RC, but definitely with the final release.

See #8444
2025-03-12 14:41:32 +01:00
Florian Bruhin 8c2cfe8f7e tests: Fix handling of qapp_args
Until now, if the seccomp bpf sandbox needs to be disabled,
PaintHoldingCrossOrigin was not disabled anymore.
2025-03-12 11:32:22 +01:00
Florian Bruhin c35fc88211 tests: Disable BPF sandbox with glibc 2.41
Fixes #8507
2025-03-12 11:29:12 +01:00
Florian Bruhin 90c40152ed Simplify getting signal for renderer process exit 2025-03-11 19:30:33 +01:00
Florian Bruhin 27606f2fe3 Show signal names on renderer process crashes
Makes debugging issues easier.
2025-03-11 19:10:49 +01:00
Florian Bruhin 561986cad8 tests: Clear messages between test cases
Makes watching the UI (or screenshots) more useful as we don't have any
leftovers from previous tests.
2025-03-11 18:51:12 +01:00
Florian Bruhin 2810021896 Qt 6.9: Adjust version numbers
See #8444
Also see #4914
2025-03-11 18:01:45 +01:00
Florian Bruhin a875f3e8be Qt 6.9: Adjust pakjoy ID
See #8444
2025-03-11 18:01:45 +01:00
Florian Bruhin 7b4c163142 Qt 6.9: Add additional error message ignores
See #8444
2025-03-11 18:01:45 +01:00
toofar 8b2ab6b01d
Merge pull request #8505 from qutebrowser/update-dependencies
Update dependencies
2025-03-11 20:03:38 +13:00
toofar 4f985feede update changelog URL 2025-03-10 23:05:00 +13:00
qutebrowser bot 2efaf92b7c Update dependencies 2025-03-10 04:20:15 +00:00
toofar a0fd88aac8
Merge pull request #8497 from qutebrowser/update-dependencies
Update dependencies
2025-03-04 08:56:43 +13:00
toofar 42c9973c01 update isort changelog link 2025-03-03 19:45:58 +13:00
qutebrowser bot c9374fd80a Update dependencies 2025-03-03 04:22:07 +00:00
qutebrowser bot dd66300caf Update dependencies 2025-02-24 10:32:38 +01:00
Florian Bruhin 33ba05c657 ci: Go back to Ubuntu 22.04 for Docker
See #8424
2025-02-24 09:43:42 +01:00
Florian Bruhin 990c4d4cfc tests: Adjust sandbox test expectations for Ubuntu 24.04
See #8424
2025-02-24 09:40:06 +01:00
Florian Bruhin 1a6d32cc3d ci: Upgrade Ubuntu versions
Avoid deprecated Ubuntu 20.04 which will be unsupported in April:
https://github.com/actions/runner-images/issues/11101

For Qt 6.8 and auxiliary jobs (linters etc.), switch from 22.04 to 24.04.
2025-02-23 22:23:01 +01:00
Florian Bruhin de8a2c04b8 bleeding: Avoid deprecated egg syntax
See https://github.com/pypa/pip/issues/13157
2025-02-23 22:00:32 +01:00
Florian Bruhin 12e6838267 bleeding: Avoid broken gherkin-official >= 31
See https://github.com/cucumber/gherkin/issues/373
2025-02-23 21:59:39 +01:00
Florian Bruhin fdfa9109ff doc: Adjust Fedora freeworld install instructions 2025-02-18 11:56:29 +01:00
Florian Bruhin 0eff340063 mypy: Enable new strict_bytes option
See https://peps.python.org/pep-0688/#no-special-meaning-for-bytes
2025-02-17 10:55:22 +01:00
Florian Bruhin eb2e39de1e scripts: Add new bump-my-version deps 2025-02-17 10:55:22 +01:00
Florian Bruhin 0b221d3e24 mypy: Fix new mypy issues 2025-02-17 10:55:22 +01:00
qutebrowser bot f7c8c67818 Update dependencies 2025-02-17 10:55:22 +01:00
Florian Bruhin accce7fdef Update urlmatch tests for Python fixes
https://github.com/python/cpython/issues/78541
https://github.com/python/cpython/issues/105704
https://github.com/python/cpython/pull/129418
2025-02-17 09:57:44 +01:00
Florian Bruhin 718d66fb6d Merge remote-tracking branch 'origin/pr/7591' 2025-02-15 16:10:24 +01:00
Florian Bruhin 60f526d81f Add new changelog URLs from bump-my-version 2025-02-03 18:40:35 +01:00
qutebrowser bot 4004799f2c Update dependencies 2025-02-03 16:55:59 +00:00
Florian Bruhin 1615e8a40e Merge remote-tracking branch 'origin/pr/8462' 2025-02-03 17:45:48 +01:00
qutebrowser bot bfb580ee91 Update dependencies 2025-02-03 11:01:24 +01:00
Florian Bruhin 4a1a30bc33 Add security patch version for Qt 6.8.2 2025-02-03 10:55:23 +01:00
Jun Chen 6b3901ccee chore: update bumpversion configuration to disallow dirty working directory and fix version replacement 2025-01-31 11:36:13 -07:00
Jun Chen 6b25fdf648 chore: replace bump2version with bump-my-version 2025-01-30 19:14:38 -07:00
sarabande 9bae38ede6
Merge branch 'qutebrowser:main' into main 2025-01-30 11:04:39 -07:00
Florian Bruhin 7bd941cda0 Make duplicate notification IDs non-fatal
The notification.Error there is unhandled otherwise.
2025-01-30 12:59:43 +01:00
Jun Chen e63781d49b docs: update contributing guide with new issue tracker link 2025-01-29 22:38:59 +01:00
Jun Chen 03224a0015 docs: update contributing guide with new issue tracker link 2025-01-29 13:39:35 -07:00
Florian Bruhin 322977dc0d Update changelog URLs for twine upgrade 2025-01-27 16:15:28 +01:00
qutebrowser bot 60177ab975 Update dependencies 2025-01-27 04:21:24 +00:00
qutebrowser bot 9b59cd02cb Update dependencies 2025-01-20 08:25:56 +01:00
Florian Bruhin b3090870d3 scripts: Rename test_requirements function
Falsely flagged by https://github.com/m-burst/flake8-pytest-style/blob/master/docs/rules/PT028.md
2025-01-19 11:56:42 +01:00
qutebrowser bot 253a818ecc Update dependencies 2025-01-13 04:22:20 +00:00
Florian Bruhin 0a32d6fef5 Fix qt69_ci_flaky marker
Follow-up to ed8141cb4b
2025-01-09 11:51:45 +01:00
Florian Bruhin c5395c23f7 Update changelog 2025-01-09 11:51:45 +01:00
Florian Bruhin d272804126 Disable DocumentPictureInPicture API
The DocumentPictureInPicture JS API added in Chromium 116 is not implemented in
QtWebEngine. This results in createWindow() being called with a window type with
random value, which then causes qutebrowser to bail out:

    Traceback (most recent call last):
    File ".../qutebrowser/browser/webengine/webview.py", line 123, in createWindow
        raise ValueError("Invalid wintype {}".format(debug_type))
    ValueError: Invalid wintype 843995690

Until this is fixed in Qt, we pass an argument to Chromium to disable the API
entirely, so that web pages hopefully fall back to something else.

In the case of the new Google Huddle feature, this results in them still working
with an on-page overlay instead.

Thanks to Joshua Cold and Vivia for helping to debug this!

Fixes #8449
See https://bugreports.qt.io/browse/QTBUG-132681
2025-01-09 11:51:45 +01:00
Florian Bruhin ed8141cb4b tests: Improve handling of qutescheme on Qt 6.9 CI
See #8444
2025-01-06 15:14:21 +01:00
Florian Bruhin 2b8c053aee Merge branch 'update-dependencies' 2025-01-06 15:07:30 +01:00
Florian Bruhin 7eb9bc45de Adjust Pillow changelog URL 2025-01-06 15:05:02 +01:00
Florian Bruhin 7d1179e0e3 Fix mypy issues after 1.14 upgrade
mypy does not do type narrowing with "in":
https://github.com/python/mypy/issues/12535

And mypy now knows that those values can be None:
https://github.com/python/typeshed/pull/12936
2025-01-06 14:46:22 +01:00
Florian Bruhin 977c90939c tests: Add --qute-strace-subprocs flag
Was needed for #8444 debugging, but might be useful for other issues with
qutebrowser subprocesses as well.
2025-01-06 12:30:19 +01:00
qutebrowser bot 980105aa11 Update dependencies 2025-01-06 04:23:13 +00:00
Florian Bruhin 3934d727e4 Qt 6.9: xfail failing test on CI for now
Probably not our fault, and shouldn't break CI until we figure out what could be
going on there...

See https://github.com/qutebrowser/qutebrowser/issues/8444#issuecomment-2569610110
2025-01-03 19:04:36 +01:00
Florian Bruhin 3144264a9d First adjustments for Qt 6.9
See #8444
2025-01-03 16:45:39 +01:00
Florian Bruhin a52f378787 Add qute-translate-popup to userscript list 2025-01-03 15:45:56 +01:00
qutebrowser bot 1bcb536a44 Update dependencies 2024-12-14 22:28:12 +01:00
Florian Bruhin 3f5ce51502 ci: Back to Ubuntu 22.04
Follow-up to 531b28771c as some stuff broke
2024-12-14 22:27:15 +01:00
qutebrowser bot 5c899e304f Release v3.4.0 2024-12-14 20:51:45 +00:00
Florian Bruhin 5a153d76ea Use/recommend libegl1 without -mesa
libegl1-mesa was a "transactional dummy package" as early as Ubuntu 20.04, and
got removed in 22.04.

See https://packages.ubuntu.com/search?keywords=libegl1-mesa&searchon=names&suite=all&section=all
2024-12-14 21:50:10 +01:00
Florian Bruhin 531b28771c ci: Upgrade some jobs from Ubuntu 20.04 to 24.04
Ubuntu 20.04 will be EOL in April 2025, and PyQt 6.8 does not support being
installed on it anymore:
https://pyqt-builder.readthedocs.io/en/stable/releases.html

Other than for the oldest Qt 5 / Qt 6 envs, and for utility envs, let's use
Ubuntu 22.04 or 24.04.
2024-12-14 21:20:15 +01:00
Florian Bruhin 2546c0746d Update changelog 2024-12-14 21:08:01 +01:00
Florian Bruhin 68e52903ae Update user agents 2024-12-14 21:05:28 +01:00
Florian Bruhin e643f8f881 Fix misc linting
Not strictly required here as it's Qt6-only, but fine
2024-12-13 13:03:31 +01:00
Florian Bruhin a0bbcd6259 requirements: Remove index-url again
Now on PyPi, partially reverts 3a956b4097
2024-12-13 13:03:31 +01:00
Florian Bruhin c563e2d302 mypy: Be more clever about Qt 6.8 2024-12-13 13:03:31 +01:00
Florian Bruhin 4a5515666e Revert "js: Set eslint to ecmascript 2020"
This reverts commit 86e2573c39.
Breaks stuff with QtWebKit, whoops...
2024-12-13 13:03:31 +01:00
Florian Bruhin b5e9cf85df mypy: Update ignores for PyQt 6.8 2024-12-13 13:03:31 +01:00
qutebrowser bot 6c7fd52b8e Update dependencies 2024-12-13 13:03:31 +01:00
Florian Bruhin c462cf62e4 pdfjs: Add some comments to polyfills 2024-12-10 22:15:00 +01:00
Florian Bruhin 86e2573c39 js: Set eslint to ecmascript 2020
Needed for the ?. operator which is supported since Chromium 80:
https://caniuse.com/mdn-javascript_operators_optional_chaining

Also makes eslint enforce trailing commas for function calls, which seems fine.
2024-12-10 22:14:48 +01:00
Florian Bruhin f8ce3a932c ci: Upgrade node version
Not strictly necessary, just a drive-by fix.
2024-12-10 17:47:12 +01:00
Florian Bruhin 666b7d4df0 pdfjs: Make eslint happy about polyfills 2024-12-10 17:45:13 +01:00
Florian Bruhin 9d1ca7cbf5 pdfjs: Move polyfills to separate file 2024-12-10 17:39:10 +01:00
Florian Bruhin 9e70ffeaad Switch to legacy PDF.js build
The normal PDF.js build only officially supports the latest Chromium, so things
might break every once in a while with QtWebEngine (e.g. #8199, #7335).

Let's instead bundle and recommend the legacy build.

Closes #8332
Closes #7721 (reworded)
Also see #7135
2024-12-10 11:47:39 +01:00
Florian Bruhin e7b346ecf2 scripts: Try harder to 'hdiutil create' the .dmg
See https://github.com/actions/runner-images/issues/7522#issuecomment-2527820259
2024-12-10 10:31:47 +01:00
Florian Bruhin c0c3caead5 Add Qt 5.15.18 Chromium version 2024-12-10 08:28:35 +01:00
Florian Bruhin 8f274c4e18 mkvenv: Add arm64 to supported platforms 2024-12-10 00:47:04 +01:00
Florian Bruhin f056f49bd1 tests: Fix file path matching on Windows
Qt 6.8 change?
2024-12-10 00:35:29 +01:00
Florian Bruhin d91750f5ae tests: ignore another bogus Chromium message 2024-12-10 00:33:21 +01:00
Florian Bruhin 54839c59e4 py313: Fix root paths in tests on Windows
https://docs.python.org/3/whatsnew/3.13.html#os-path
"On Windows, isabs() no longer considers paths starting with exactly one slash
(\ or /) to be absolute."

See https://github.com/python/cpython/issues/44626
and #8205
2024-12-09 23:50:00 +01:00
Florian Bruhin 728fe7625b Fix pylint 2024-12-09 23:49:54 +01:00
Florian Bruhin 9e8ea8eee4 tests: Re-add flaky marker
See 258e61f97c - unfortunately still flaky
2024-12-09 22:55:44 +01:00
Florian Bruhin a51b631d26 Fix mypy 2024-12-09 22:52:12 +01:00
Florian Bruhin 45d04be1c9 py313: Also ignore cheroot error on Windows
See #8205
2024-12-09 22:49:29 +01:00
Florian Bruhin 68eacd2036 py313: Avoid deprecated pathlib.PurePath.is_reserved()
Looks like the CI upgrade was the first time we tested this on Windows?
Whoops!

https://github.com/python/cpython/issues/88569
https://docs.python.org/3/whatsnew/3.13.html#new-deprecations
See #8205
2024-12-09 20:57:05 +01:00
Florian Bruhin 258e61f97c tests: Stabilize reloading in tests
The test added in fbd148f983 was flaky because
reloading didn't wait for the page load to actually finish fully, and thus the
element not being found on the page.

Fix this by providing the page path to the step, and making sure it waits for it
to be fully loaded again.

Also undos some flaky tags done in 2018:
12e5375931
c1c182d958

As this might have been the real culprit.
If not, those should be re-added.

See #8348, #5390
2024-12-09 20:48:45 +01:00
Florian Bruhin 3a956b4097 ci: Add preliminary PyQt 6.8 environment
See #8242
2024-12-09 20:16:27 +01:00
Florian Bruhin bb652cc108 ci: Fix up Python versions
Follow-up to b1ad5c2e30
2024-12-09 20:14:10 +01:00
Florian Bruhin d45de75129 tox: Remove Python 3.13 typing-extensions handling
See #8205
2024-12-09 20:11:45 +01:00
Florian Bruhin 061c1f0f85 Fix lint 2024-12-09 17:57:21 +01:00
Florian Bruhin 54b220348f Fix lint 2024-12-09 17:32:07 +01:00
Florian Bruhin 960d9aaaa5 tests: Initialize QtWebEngine spell dictionary path earlier
Turns out there are various places in the tests that somehow cause Qt to start
caching the dict location, not just actually accessing
.[is|set]SpellCheckEnabled() like I originally assumed.

Thus, move setting QTWEBENGINE_DICTIONARIES_PATH into conftest.py so it's run
before any tests. However, remove the sanity check after, as that requires
initializing a QWebEngineProfile which we might not always want to do when
running a subset of unit tests. If something goes wrong with this, chances are
we'll only notice later in the tests anyways.

Follow-up to db8e508530
See #8330
2024-12-09 17:26:12 +01:00
Florian Bruhin c501ae375e scripts: Close sqlite connections properly in importer
Found thanks to runnning Python 3.13 tests on CI.

See #8205
2024-12-09 16:51:55 +01:00
Florian Bruhin 4918e6d8ff macOS: Avoid deprecated file associations
Based on Chromium's Info.plist.

Fixes #7306, see #8416 for more possible improvements.
2024-12-09 16:41:24 +01:00
Florian Bruhin 946ec0ab25 py313: Update docs
See #8205
2024-12-09 16:15:01 +01:00
Florian Bruhin b1ad5c2e30 ci: Use Python 3.13
- Newest Linux/macOS/Windows environments (should be roughly same as release,
  especially for Windows/macOS)
- Nightly binary builds
- Release automation

Closes #8205
2024-12-09 16:14:48 +01:00
Florian Bruhin 4c7325f912 py313: Suppress cheroot warnings
https://github.com/cherrypy/cheroot/issues/734
See #8205
2024-12-09 16:08:47 +01:00
Florian Bruhin 48d3c7d97c py313: Ignore maxsplit deprecation warning
2f48300931
https://github.com/pytest-dev/pytest-bdd/issues/752
https://github.com/pytest-dev/pytest-bdd/pull/753

See #8205
2024-12-09 16:06:54 +01:00
Florian Bruhin 321898eb54 Update changelog 2024-12-09 14:45:41 +01:00
Florian Bruhin db8e508530 Fix Qt 6.8 spell checking test
Starting with Qt 6.8, Qt enforces that the spell checking dictionary path exists
when enabling spell checking (but it doesn't check whether there is actually
anything in there). This caused our test ensuring that spell checking gets
enabled properly to fail, as we never actually set a proper directory.

We now do, though we need to do so for the entire test session, as QtWebEngine
caches the directory.

Reverts 7475d38
See https://github.com/qutebrowser/qutebrowser/issues/8242#issuecomment-2333609589
Fixes #8330
2024-12-09 14:39:53 +01:00
Florian Bruhin 3cfefd121c Avoid Qt 6.8 spell check warning
Due to a Qt bug, we get a misleading error even when trying to *disable*
spell checking: https://bugreports.qt.io/browse/QTBUG-131969

To avoid that from happening, we now only call setSpellCheckEnabled() if
the value actually changed.

See #8242, #8330 (not the same issue but related)
2024-12-09 14:08:44 +01:00
Florian Bruhin d7328af221 Add JSON resource type
Added in Qt 6.8, documented as:

    a JSON module (import ... with { type: "json" })

See #8242
2024-12-09 14:05:37 +01:00
Florian Bruhin 4d5ed99ff5 link_pyqt: Try QtCore before sip
Makes for nicer error messages if there's no PyQt at all.
2024-12-09 13:59:33 +01:00
qutebrowser bot 5d3df09146 Update dependencies 2024-12-09 11:25:49 +01:00
Florian Bruhin 557cd19a1d ci: Try harder to detach dmg image
See https://github.com/actions/runner-images/issues/7522
2024-12-06 21:45:27 +01:00
Florian Bruhin 6c9fd35bfa Update changelog 2024-12-06 20:49:14 +01:00
Ruben Gonzalez 3a3c03a4df In POSIX sh, echo flags are undefined 2024-12-06 19:40:28 +00:00
Florian Bruhin 3dce208237 Use Python 3.12 for nightly builds 2024-12-06 20:39:58 +01:00
Florian Bruhin 5cb14d4d4b Run shellcheck over all scripts/*.sh files
See #8409
2024-12-06 20:39:34 +01:00
Florian Bruhin a7b566e7b3 Remove pytest-bdd<8 limit 2024-12-06 14:53:03 +01:00
Florian Bruhin acc06cdd39 Merge branch 'gherkin8342' 2024-12-06 14:52:08 +01:00
Florian Bruhin e2fb1fba8b Revert "Bleeding requirements: Use pytest-bdd release"
This reverts commit 26b4ec6cef.
2024-12-05 19:27:10 +01:00
Florian Bruhin aed06c5f48 Add gherkin-official changelog URL 2024-12-05 19:26:58 +01:00
Florian Bruhin 59fd7876a1 pytest-bdd 8: Fix borked tag 2024-12-05 19:15:47 +01:00
Florian Bruhin f91dc2d52d pytest-bdd 8: Adjust Python code for multiline steps 2024-12-05 16:19:46 +01:00
Florian Bruhin f4260a6e55 pytest-bdd 8: Fix comments and remaining syntax issues
Looks like inline comments are not permitted anymore.
2024-12-05 16:19:29 +01:00
Florian Bruhin a8a5068e62 pytest-bdd 8: Fix missing multiline step quoting 2024-12-05 16:13:04 +01:00
Florian Bruhin cec00266d0 pytest-bdd 8: Fix tags
Tags containing spaces aren't supported anymore, so we can't add additional skip
descriptions sadly...
2024-12-05 16:11:17 +01:00
Florian Bruhin bb462c2602 pytest-bdd 8: Fix indentations 2024-12-05 16:05:59 +01:00
Florian Bruhin f524926216 Fix tab indentation in feature files 2024-12-05 15:39:56 +01:00
Florian Bruhin 629a38d654 Upgrade to pytest-bdd 8 2024-12-05 15:36:18 +01:00
Florian Bruhin e15d266309 Merge branch 'xhr-accept-language'
# Conflicts:
#	doc/changelog.asciidoc
2024-12-05 15:08:28 +01:00
Florian Bruhin f3d280ba53 Expand comment 2024-12-05 15:04:56 +01:00
Florian Bruhin e158a480f5 Add QtWebEngine 6.8.1 Chromium security version 2024-12-04 21:17:03 +01:00
Florian Bruhin 69ac04d389 Drop macOS 12
The GHA runner is gone now: https://github.com/actions/runner-images/issues/10721

Closes #8327
2024-12-04 20:56:22 +01:00
Florian Bruhin df75956cf9 Update docs 2024-12-04 20:51:58 +01:00
Florian Bruhin a1d89a83b0 Merge remote-tracking branch 'origin/pr/8348' 2024-12-04 20:40:19 +01:00
Florian Bruhin 06501886eb
Merge pull request #8406 from qutebrowser/update-dependencies
Update dependencies
2024-12-02 04:46:24 +00:00
qutebrowser bot e6a0446a92 Update dependencies 2024-12-02 04:20:49 +00:00
toofar 40adc6696b
Merge pull request #8397 from qutebrowser/update-dependencies
Update dependencies
2024-12-01 20:29:22 +13:00
Florian Bruhin a397aa069e Also handle QtWebKit Accept-Language correctly
On QtWebKit, we only set Accept-Language in the request interceptor.
2024-11-27 18:10:00 +01:00
Florian Bruhin 0144a314ad Respect Accept-Language set via XHR
Similarly to #5998, XHR requests should be able to set their custom
Accept-Language values - and for some odd reason, stuff breaks on websites
sometimes when that's not respected.

There's no way for qutebrowser to know if a given header value is already set in
a request (i.e. whether we're adding or overriding). Thus we only really have
two options here:

1) Don't set any shared.custom_headers() for XHR requests at all.
2) Special-case Accept-Language here, because the issue usually is triggered by
the global override, but that already gets set just fine via QWebEngineProfile
anyways.

Given that 2) is the thing causing trouble in the wild and it's unclear what the
desired behavior for 1) is (e.g. for the DNT header), let's go for 2) here.
2024-11-27 17:48:03 +01:00
Florian Bruhin ddac8a16bf Simplify assert 2024-11-26 15:21:24 +01:00
qutebrowser bot 17792f87e8 Update dependencies 2024-11-25 04:20:31 +00:00
Florian Bruhin 2ba07fe490
Merge pull request #8387 from qutebrowser/update-dependencies
Update dependencies
2024-11-24 00:30:52 +00:00
Florian Bruhin 3608b2b3be Pin pytest-bdd<8
See https://github.com/qutebrowser/qutebrowser/issues/8342
2024-11-24 01:09:01 +01:00
dependabot[bot] 4b7cc881ec Bump codecov/codecov-action from 4 to 5
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4 to 5.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-24 00:06:49 +00:00
toofar 77c880544f fix test for webkit
Was getting an import error when trying to import the webengine version.
Not going to skip the tests using this step since they seemed to be
working otherwise, probably this behavior isn't needed on webkit anyway.
2024-11-23 12:15:33 +13:00
toofar 66759c7172 Check pyqt version against hex number, not str
A string comparison of version numbers relies on nice simple version
numbers with approximately the same amount of digits. Who knows what
various systems are running!

Switch to the integer format version number. It's harder to grep for
when dropping a Qt version, but hopefully we have enough "6.8"s around
it to compensate.
2024-11-23 12:15:33 +13:00
toofar 427fb47e0c add copyright header to test file
review feedback

Hopefully this is an okay header format for checkers to pick up, it's
the same as in qutebrowser/html/version.html except with the doctype
declaration above.
2024-11-23 12:15:33 +13:00
toofar 1888944a69 minimize conditional expression
review feedback

I've mixed opinions on this. I'm not convinced that ternary expressions
are more readable than an if/else block.

Also if someone passes a string into this function it'll return
"access-paste" now.
2024-11-23 11:36:14 +13:00
Aryan Dev Shourie 590a602e57 capitalized github text to maintain consistency 2024-11-22 17:01:59 +00:00
qutebrowser bot 664c554bf6 Update dependencies 2024-11-18 04:22:39 +00:00
toofar 6d9563035e Add test checking `Feature(8)` == ClipboardReadWrite
Co-Authored-By: Florian Bruhin <me@the-compiler.org>
2024-11-17 19:48:40 +13:00
toofar a085e3caa0 use `unlink(missing_ok=True)`
Combine the `if exists` and `unlink` in one step and avoid any race
conditions with the file disappearing in between them.

Co-Authored-By: Florian Bruhin <me@the-compiler.org>
2024-11-17 19:48:40 +13:00
toofar 4dd36aca04 Change check for new API to try/catch
Previously it would have crashed with an AttributeError if a user had a
PyQt of 6.8 but Qt of 6.7.

Switch to catching any AttributeError which will hopefully cover
either or both of Qt and PyQt not being a new enough version, even if
it's a bit less of an explicit check.
2024-11-17 19:48:40 +13:00
Florian Bruhin 07bd9a691a tests: Ignore irrelevant Chromium warning 2024-11-11 12:53:29 +01:00
qutebrowser bot c03d3dd6ac Update dependencies 2024-11-11 10:23:04 +00:00
Florian Bruhin af884a02c8 ci: Upgrade codecov action 2024-11-10 20:01:44 +01:00
Florian Bruhin a04126b22b hypothesis: Inherit our CI settings from hypothesis CI profile
See 13c3785854

deadline=None and suppressing the too_slow health check is already part of that.
Also fixes a hypotheses -> hypothesis typo.
2024-11-10 19:40:54 +01:00
Florian Bruhin f382a1a18f Remove pytest-benchmark filterwarning 2024-11-10 19:36:51 +01:00
Florian Bruhin c075f6650e Merge remote-tracking branch 'origin/update-dependencies' 2024-11-10 19:36:21 +01:00
toofar 57465a6768 Assert on unexpected config value when prompting
This branch gets entered if the value of a setting linked to a feature
is anything other than True, False or "ask". I think this could only
happen due to a programming error, for example when you add an entry to
`_WebEnginePermissions` that was linked to a String type setting. So I
think putting an assert here instead of a warning should be fine and
more explicit. (Or should be be `utils.Unreachable`? Or `ValueError`?)
2024-11-10 14:38:47 +13:00
Florian Bruhin 49e67c4dc9 Fix up changelog
See #7625
2024-11-07 14:58:47 +01:00
qutebrowser bot b495e78b8a Update dependencies 2024-11-04 04:20:40 +00:00
toofar 1127c0de19
Merge pull request #8359 from qutebrowser/update-dependencies
Update dependencies
2024-10-29 11:17:56 +13:00
toofar 7535207fd3 Merge remote-tracking branch 'upstream/main' into feat/68_permissions_askeverytime 2024-10-29 10:22:44 +13:00
toofar e55624703b Move config-type-to-bool thing to an abstract class
Relying on `hasattr()` made me feel a bit guilty. So I've moved these
conditionals to be backed by a class. The only class based alternative I
can think of is putting it on the base type and leaving all the other
config variables to raise errors. But that doesn't tell the type system
anything.
2024-10-29 10:20:56 +13:00
toofar fbd148f983 Support persisting clipboard prompt choices
All the promptable feature permissions so far have been of type BoolAsk.
The prompt uses a "yesno" mode prompt and only results in a bool. The
persistence logic only supports bools.

Previously I made the shared prompt support the String type clipboard
permission setting by treating non "ask" values as False (you only get
prompted if the global setting is "none" anyway), but saving the prompt
results with `:prompt-accept --save` didn't work because the persistence
code only supported bools.

What we want to do when saving is convert `False` to "none" and `True`
to "access-paste". This mirrors the new webengine logic. It does mean we
can't let users choose to persist either none/access/access-paste, but
webengine doesn't prompt us if the page is already allowed "access" but
is trying to paste anyway. If it did we would have to use a non-yesno
prompt for this (perhaps it could be driven directly by the ConfigType).

For now I've added a new concept to the ConfigTypes to allow them to be
casted to and from bools, so that we can plumb this String type from the
boolean yesno prompt.

TODO:
* try to make it an interface so we don't have to use `hasattr` (even if
  it means multiple inheritance)
* add test coverage to test_configtypes.py
2024-10-29 10:05:21 +13:00
qutebrowser bot 643bdf7305 Update dependencies 2024-10-28 04:21:24 +00:00
toofar 4c3337f553 Skip clipboard end2end tests on webkit
The test page is using a JS API that is too new for qtwebkit:

    23:07:54.898 DEBUG    js         shared:javascript_log_message:190 [http://localhost:37635/data/prompt/clipboard.html:97] TypeError: undefined is not an object (evaluating 'navigator.clipboard.readText')
2024-10-28 15:26:25 +13:00
toofar f891dd3137 Wait for quteproc shutdown in across-restarts prompt test
This is failing with:

    ERROR tests/end2end/test_invocations.py::test_permission_prompt_across_restart - PermissionError: [WinError 5] Access is denied: 'C:\\Users\\RUNNER~1\\AppData\\Local\\Temp\\tmpytep6gj0\\cache\\webengine\\Cache\\Cache_Data\\data_0'

In pytest teardown, while trying to clean up a temp dir, probably the
basedir. The test above waits for shutdown at the end of the test, maybe
that's what's needed here.

Otherwise maybe just `@pytest.mark.skipif(utils.is_windows)` 🤷
2024-10-28 15:26:25 +13:00
toofar 28890f6fbb Change `content.javascript.clipboard` default to `ask`
Now that we support prompting for clipboard access, change the default
for this setting to match all the other settings that have an "ask"
value.
2024-10-28 15:26:25 +13:00
toofar f551bbbb76 Move new permission API check from pytest markers to BDD step
For tests that do the same prompt in the same session, they are failing
on Qt6.8 and PyQWebEnginet6.7 because we can't disable the new WebEngine
behaviour.

We can work around this by getting a fresh instance for each test, but I
don't want to make more tests slower if I don't have to. So move that
logic into a custom "fresh instance" prompt that will only create one
when needed.
2024-10-28 15:26:25 +13:00
toofar 0192b58a6a Support 'ask' for clipboard permissions
WebEngine now supports prompting for permission when a web page tries to
access the clipboard. Previously we only supported fixed permissions that
applied globally.

This commit

1. adds support for permission requests with the new ClipboardReadWrite
   permission
2. tweaks the generic JS prompt handler in browser/shared.py to handle
   seeing a setting which isn't of type BoolAsk
3. adds end2end tests around clipboard permissions, both the existing
   global ones and the new per-URL ones

1. the ClipboardReadWrite permission

I added this as an int because the relevant PyQt isn't out yet and users
with 6.8 running with PyQt6.7 are already seeing this.

I added an "ask" value to the existing String type
`content.javascript.clipboard` setting and set the
default/global/fallback permissions to False if ask is set globally.
Hmm, maybe we should change the default actually... I'll have to check
what the other prompt supporting settings default to.

2. tweaked prompt handler

This was treating the string values that weren't "ask" (like "none" and
"access") as truthy and allowing the action. I've changed the bool
checks to be exact checks to add a warning if this happens again.

Then I added an exception to the warning logging for known cases like
this. I did try looking at adding a new setting type. Something that was
descended from String but had an `__eq__` method that understood bools
and would treat `access-paste` as True and everything else as False. But
that didn't work out because it looks like config values are stored as
python values and the config classes are just static and don't actually
hold values. Oh well, maybe a better pattern will emerge with time.

3. tests

Apparently there were no tests around the clipboard settings. Perhaps
not a coincidence given how confusing they are (what does access-paste
mean?).

I copied a test file from some random test site, tweaked it a little bit
and got to work. For the paste test it's a bit awkward because I don't
know if we have a way to fill the clipboard in a nice way for the tests.
So I'm just matching on "Text pasted: *", which is usually an empty
string.

The prompt tests require running against Qt6.8 to get the new prompt
behaviour (don't need pyqt68 though).
2024-10-28 15:26:25 +13:00
toofar 4fab7b4357 Add clipboard permission tests
There are some changes in this area in Qt6.8, so it would be good to
have some test coverage.

The "access permission - copy" one is broken in 6.8. Still need to raise
that upstream.
2024-10-27 13:42:35 +13:00
toofar 5ad68024b2 mypy: ignore pyqt attribute from the future
Once pyqt 6.8 is released mypy will probably start complaining about an
unnecessary ignore statement and we can remove it.
2024-10-27 12:48:53 +13:00
toofar 8064e3ea6f Disable QtWebEngine's permissions persistence feature
QtWebEngine has a new feature where it will remember what permissions
you have granted or denied. It has three options regarding permissions
storage:

    AskEveryTime -- don't store
    StoreInMemory -- store in memory only
    StoreOnDisk -- store in memory and on disk

By default it does the StoreOnDisk behavior. Having webengine remember
whether you granted or denied a permission would make the qutebrowser UX
around that area inconsistent. For example the default y/n actions for a
permission prompt in qutebrowser will only accept that single
permission request, and you'll be re-prompted if you reload the page.
Users may be used to this and if webengine started remembering
permission grants the users may be surprised to find that the page was
accessing features without prompting them for permission anymore.
Additionally we already have our own permission storage machinery in
autoconfig.yml.

This commit will set the webengine feature to AskEveryTime, which disables
any storing of permission grants.

Also adjusts the skip marker of the affected tests so they'll be enabled
again on Qt versions with the appropriate permissions API.
2024-10-27 12:48:46 +13:00
Florian Bruhin a138ab8978 Fix some broken links 2024-10-22 18:17:08 +02:00
Florian Bruhin d49675eeed Remove outdated version check 2024-10-22 18:10:19 +02:00
qutebrowser bot ad29c973f8 Update dependencies 2024-10-21 12:32:07 +02:00
Florian Bruhin dc5662b141 Update chromium release dates 2024-10-21 10:28:32 +02:00
Florian Bruhin 58dec07d27 Tests: Catch error with :tab-next/:tab-prev and no tabs
Ref #1448
2024-10-17 10:01:10 +02:00
bosshogg 85435c7574 Revert change to _count
Adds a specific check for only -1 in _current_index
2024-10-16 18:40:44 +02:00
bosshogg 5691e04afc Remove duplicate checking of widget existence
_run_userscript handles the case different than _current_index()
2024-10-16 17:20:08 +02:00
bosshogg 9fc6ea0434 Fix checks failing on first tab 2024-10-16 17:13:01 +02:00
Marcel Schilling 2aacfe1a8c
Rewrite `.feature` files to use the `"""` syntax
fixes #8342
2024-10-15 15:17:45 +02:00
Florian Bruhin af835c26ad Update changelog 2024-10-15 12:00:25 +02:00
Florian Bruhin ffe7d00a62 Merge branch 'drop-py38' 2024-10-15 11:58:54 +02:00
toofar cc3c1e2050 Enable pylint Too many positional arguments warning
This re-enables the pylint too-many-positional-arguments for the main
application code. It's still disabled for tests because that's how you pull in
pytlint fixtures, and I don't think we want to push people into being creative
with fixtures just to get around that.

When functions are called with many positional arguments the reader has to do
a bit of heavy lifting to figure out in what position a value is being passed,
and it's easier to make mistakes. So I would like to encourage using keyword
arguments for long argument lists.

I've set the `max-positional-arguments` to a completely arbitrary 7, from a
completely arbitrary 5, because there were many more violations under 7. If
like 99% of our functions fit under 7 it's probably fine.

Regarding the exceptions:
* objreg.register: I grepped it and it looks like everything is only passing
  the first two args as positional already, lucky!
*  `_get_color_percentage`: only one usage of it, but I was in "add directive
  comment" mode
* update_3rdparty.py: only one usage, already using kwargs
* pyqtProperty: idk
* commands.py: "its complicated". Many methods in this file map to commands
  used in qutebrowser's command mode. In that case it's usual for them to be
  called as flags, rather than positional. But it could be complicated to wade
  into that, and having one file excluded isn't so bad.
2024-10-15 11:55:04 +02:00
Florian Bruhin ff5d4d3564 Avoid passing a parent to QProcess
With the upgrade to MarkupSafe 3.0, something funny happened when trying to pass
the GUIProcess object to jinja after launching a userscript:

    [...]
    File "[...]/qutebrowser/browser/qutescheme.py", line 291, in qute_process
        src = jinja.render('process.html', title=f'Process {pid}', proc=proc)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "[...]/qutebrowser/utils/jinja.py", line 123, in render
        return environment.get_template(template).render(**kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    [...]
    File "html/process.html", line 11, in block 'content'
    File "[...]/lib/python3.11/site-packages/markupsafe/__init__.py", line 42, in escape
        if hasattr(s, "__html__"):
           ^^^^^^^^^^^^^^^^^^^^^^
    RuntimeError: wrapped C/C++ object of type GUIProcess has been deleted

This can be reproduced with:

    qutebrowser --temp-basedir ':cmd-later 0 spawn -u -o /bin/echo test'

We pass the `GUIProcess` to the Jinja template as `proc`, which then formats it as
`{{ proc }}`` (to stringify it). For some reason, with the newest MarkupSafe/Jinja
versions, this now triggers the `if hasattr(s, "__html__")` check in MarkupSafe
(which has been around for a while). That then presumably causes PyQt to try and
access the underlying C++ object for `GUIProcess``, but that has already been
deleted.

But why is it deleted in the first place, if we keep track of even completed
processes data ever since we added `:process` in a3adba81c? It looks like the Qt
parent-child relationship is the culprit here: When we pass a parent to the
`GUIProcess`` from the userscript runner, it will get deleted as soon as said
runner is cleaned up (which happens after the userscript has finished).

We probably never noticed this before because we only accessed data from the
Python wrapper and not from the C++ side, but it still seems like a good idea
to avoid passing a parent for a long-lived object (with time-based cleanup) in
the first place.
2024-10-15 11:55:04 +02:00
Florian Bruhin f175f611f8 pylint: Disable too-many-positional-arguments
Added in 3.3.0:
https://pylint.pycqa.org/en/latest/whatsnew/3/3.3/index.html

Some of those arguments could probably indeed be keyword-only,
but for some of the functions shown by pylint, those are qutebrowser command
handlers where a positional argument has different semantics.
2024-10-15 11:55:04 +02:00
Florian Bruhin ab7d04a951 Fix wrong type annotation
This was wrong ever since 0a835ecd92,
but due to the version conditional usage, mypy did not check it.
2024-10-15 11:55:04 +02:00
Florian Bruhin 2ab963cef8 Remove pytz changelog URL 2024-10-15 11:55:04 +02:00
Florian Bruhin 7083fee655 Recompile requirements 2024-10-15 11:55:04 +02:00
Florian Bruhin cc18a624b5 Remove importlib_resources from requirements 2024-10-15 11:55:04 +02:00
Florian Bruhin 0fd6fc19f2 recompile_requirements: Fix with diff.mnemonicPrefix set 2024-10-15 11:55:04 +02:00
Florian Bruhin 088b5973eb Update mimetype overrides
See https://github.com/python/cpython/commits/main/Lib/mimetypes.py
2024-10-15 11:55:04 +02:00
Florian Bruhin eb8121ffd5 Use Callable from collections.abc as well
Did run with ruff pretending to use Python 3.10,
because otherwise it won't reformat those:

    ruff check --select 'UP035' --fix --config 'target-version = "py310"' --unsafe-fixes

This is because collections.abc.Callable inside Optional[...] and Union[...] is
broken with Python 3.9.0 and 3.9.1:

https://github.com/asottile/pyupgrade/issues/677
https://github.com/astral-sh/ruff/issues/2690
https://github.com/python/cpython/issues/87131

However, pylint can detect problematic usages (of which we only have one),
so we might as well use the new thing everywhere possible for consistency.

Also see #7098
2024-10-15 11:54:53 +02:00
Florian Bruhin 97104b2000 Use builtin list/dict/set/... types for annotations
See https://peps.python.org/pep-0585/
and https://docs.python.org/3/whatsnew/3.9.html#type-hinting-generics-in-standard-collections

Done via:

    ruff check --select 'UP006' --fix --config 'target-version = "py39"' --unsafe-fixes

followed by removing unused imports:

    ruff check --select 'F401' --fix --config 'target-version = "py39"'

and a semi-manual review to find imports that are still needed (but ruff doesn't know about yet):

    git diff | grep '^-' | grep import | grep -v "from typing"

Also see #7098.
2024-10-15 11:54:49 +02:00
Florian Bruhin c32b8090ca Import typing classes from collections.abc
See https://peps.python.org/pep-0585/
and https://docs.python.org/3/whatsnew/3.9.html#type-hinting-generics-in-standard-collections

Not changing List/Dict/Set/etc. in this commit, as that's a way bigger change.

Done via:

    ruff check --select 'UP035' --fix --config 'target-version = "py39"'

Also see #7098.
2024-10-15 11:54:35 +02:00
Florian Bruhin 8cf9cc9f1b nsis: Check for newer Windows build
Follow-up to #8321, so we only claim to support what Qt actually officially does.
2024-10-15 11:52:34 +02:00
Florian Bruhin 26b4ec6cef Bleeding requirements: Use pytest-bdd release
See https://github.com/qutebrowser/qutebrowser/issues/8342
2024-10-15 11:42:07 +02:00
Florian Bruhin 463bde5c8e Update changelog 2024-10-15 10:33:53 +02:00
Willow Barraco 61746e0f58 desktop: qutebrowser as webp mime type viewer
This is decent webp viewer, like other web browser.
2024-10-15 10:33:12 +02:00
Florian Bruhin c598cbbc71 Revert "ci: Avoid Archlinux' pyqt6 6.1.7-3 which lacks QSignalSpy"
This reverts commit 27e446d26d.
Archlinux now uses a PyQt 6.8 development snapshot.
2024-10-15 00:47:31 +02:00
toofar f895c022cb
Merge pull request #8337 from qutebrowser/update-dependencies
Update dependencies
2024-10-14 19:21:03 +13:00
qutebrowser bot 80ed616230 Update dependencies 2024-10-14 04:18:59 +00:00
bosshogg de5fbf711d Raise CommandError if there are no tabs or widgets
Show the user "No WebView avaible" when tryin to do an action on tabs or
widgets that don't exist.
2024-10-13 22:40:18 +02:00
Florian Bruhin 6bf159581e
Merge pull request #8301 from qutebrowser/dependabot/github_actions/peter-evans/create-pull-request-7
Bump peter-evans/create-pull-request from 6 to 7
2024-10-13 21:51:28 +02:00
Florian Bruhin b976a31ffa
Merge pull request #8321 from qutebrowser/feat/8260_drop_qt5_builds
Remove support for making Qt5 builds
2024-10-13 21:45:05 +02:00
Florian Bruhin 27e446d26d ci: Avoid Archlinux' pyqt6 6.1.7-3 which lacks QSignalSpy
See https://github.com/qutebrowser/qutebrowser/issues/8242#issuecomment-2409077518
2024-10-13 20:28:43 +02:00
Florian Bruhin 4d069b8fc3 Use str.removeprefix() and str.removesuffix()
https://docs.python.org/3/whatsnew/3.9.html#new-string-methods-to-remove-prefixes-and-suffixes
2024-10-13 18:24:44 +02:00
Florian Bruhin fe868901ab Remove all importlib_resources backport usage 2024-10-13 18:24:44 +02:00
Florian Bruhin 2ad1a579b1 Remove :debug-cache-stats conditionals 2024-10-13 18:24:44 +02:00
Florian Bruhin 71039e0d53 Minor Python 3.8 dropping adjustments 2024-10-13 18:24:44 +02:00
Florian Bruhin bcff1e90ea Update checkpyver for 3.8 drop 2024-10-13 18:24:44 +02:00
Florian Bruhin eb67b20417 Update docs for Python 3.8 drop 2024-10-13 18:24:44 +02:00
Florian Bruhin 5337882657 Adjust linters for dropping Python 3.8 2024-10-13 18:24:44 +02:00
Florian Bruhin 3288ec8598 Adjust Python versions in setup.py 2024-10-13 18:24:44 +02:00
Florian Bruhin bd3774dfc8 Drop Python 3.8 from tox/CI 2024-10-13 18:24:44 +02:00
Florian Bruhin 02cee732fc
Merge pull request #8334 from qutebrowser/update-dependencies
Update dependencies
2024-10-13 17:20:31 +02:00
qutebrowser bot 6093306ff5 Update dependencies 2024-10-13 14:54:29 +00:00
toofar 0ab1e3b757 Clear webengine's permissions.json on start
To avoid WebEngine remembering granted permissions across restarts,
remove their persistence file when we start up.

This is only technically required when Qt=>6.8 and PyQt<6.8. But we only
take action if the file exists anyway, so it's safe enough to run all
the time and that means less conditional code to test ;)

There are a few options for where we could do this cleanup, I'm choosing
to do it at the latest point possible, which is right before we set
`setPersistentStoragePath()`, since the permissions manager is
re-initialized after that, see https://bugreports.qt.io/browse/QTBUG-126595

TODO:
* call the new setPersistentPermissionsPolicy API when PyQt>=6.8
2024-10-13 18:52:29 +13:00
toofar dfd4fffaac Add test around remembering permissions across restart
Qt 6.8 has its own permission grant persistence features. This means
that if you accept a permission prompt in qutebrowser, and don't save
it, it will be remembered by webengine anyway and you won't be
re-prompted again.

This test demonstrates that behaviour by temporarily granting a
permission, restarting the browser in the same basedir, then seeing if
we get prompted for the permission again or not. If not it fails on the
"Asking question" line.

We can't do much about re-prompting for a permission in the same browser
instance (Qt saves the permission grant in memory too) but we can clean
up the persisted permission files on browser starts so it doesn't
remember it forever. At that point the skip mark can be removed from
this test.
2024-10-13 17:59:00 +13:00
toofar 50bf3bdd52
Merge pull request #8323 from qutebrowser/update-dependencies
Update dependencies
2024-10-13 15:19:56 +13:00
toofar 7475d385ac Comment out failing test assertion for now
Ref: https://github.com/qutebrowser/qutebrowser/issues/8330
2024-10-13 14:10:43 +13:00
Florian Bruhin 4d2aa13db3 Fix pdf.js downloading tests
See ee89bd1c39
which was part of PDF.js v4.7.76 (2024-10-06).

This should work both with the old and new version.
2024-10-12 22:20:02 +02:00
Florian Bruhin 775db2caef Update Chromium security patch versions 2024-10-12 22:19:58 +02:00
Florian Bruhin cc73134ead Add tenative v3.4.0 changelog 2024-10-12 21:50:07 +02:00
qutebrowser bot eacdca5a36 Release v3.3.1
(cherry picked from commit fc0d7e08bc)
2024-10-12 19:40:58 +00:00
Florian Bruhin 94dce5f1d4 Update release checklist 2024-10-12 21:38:20 +02:00
Florian Bruhin 7d6ea4b58b Fix up changelog 2024-10-12 21:37:17 +02:00
Florian Bruhin 5a8964dc48 Update changelog 2024-10-12 21:31:27 +02:00
Florian Bruhin 28480f394b Update the Firefox UA for quirks
See #5182
2024-10-12 21:31:27 +02:00
Florian Bruhin 5057c9a2ca Update content.headers.user_agent completions 2024-10-12 21:31:27 +02:00
bosshogg 431b2c1633 Fix zero division bug in tab-move +
Do the modulo by 1 incase self._count() is 0 or negative
2024-10-11 22:23:30 +02:00
bitraid 52a8576d7c Simplify OS version checks in nsis installer
22000 is the earliest win11 build, so no need to check for that
separately.
AtLeastWin11 is from https://github.com/kichik/nsis/blob/master/Include/WinVer.nsh#L552
Remove fail label since all failures fall through.
2024-10-09 21:40:37 +13:00
qutebrowser bot dea648ccd8 Update dependencies 2024-10-07 04:22:07 +00:00
toofar 3a48111e53 update node version for eslint
Github is updating all their actions to node 20, may as well do the same
here? Not strong need to update it, just spotted this.
2024-10-05 13:55:15 +13:00
toofar d24a4c5ab0 Remove Qt5 switches from release building scripts etc
I just searched for qt5 and deleted stuff. EZ.
Will leave on a branch for a bit and see if I feel like testing this at
all, otherwise maybe leave this stuff in here and make it not called.

Not 100% sure that we need to remove all this stuff when we just want
the CI to go green. But tbh if we don't need to make Qt5 releases then
we don't need it. Better to be bold and pull it out than have to work
around it in the future. And we can always revert the commit.
2024-10-05 13:55:15 +13:00
toofar fc9fe75033 Remove qt5 nightly jobs
They require maintenance, but we don't have a great need for Qt5 builds.
See https://github.com/qutebrowser/qutebrowser/issues/8260

All the Qt5 switches are still in tox, the build release script and the
nsis installer.
2024-10-05 13:29:50 +13:00
dependabot[bot] cff456f232
Bump peter-evans/create-pull-request from 6 to 7
Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 6 to 7.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/v6...v7)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-09 18:43:12 +00:00
Eolien55 faf692657c misc/userscripts/ripbang: Use lite.duckduckgo
The previous way of obtaining the Bang's URL was using the
response's body, using the url atrribute of a meta tag. The way
this was handled was a bit problematic: some URLs were of the format
/l/?uddg=<URL>&<some-other-query-arguments>, while others (such as google)
is simply <URL>. This could have been fixed by using an if-else, but I
preferred another approach. Lite DuckDuckGo sends a 303 response when
using Bangs, instead of a 200 response which makes the redirect. The
location header of the 303 response is the search engine's URL, so it's
easy to implement this function, working for both afformentioned URL
templates.
2023-02-26 15:47:13 +01:00
311 changed files with 5291 additions and 1834 deletions

View File

@ -1,19 +0,0 @@
[bumpversion]
current_version = 3.3.0
commit = True
message = Release v{new_version}
tag = True
sign_tags = True
tag_name = v{new_version}
[bumpversion:file:qutebrowser/__init__.py]
parse = __version__ = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)
[bumpversion:file:misc/org.qutebrowser.qutebrowser.appdata.xml]
search = <!-- Add new releases here -->
replace = <!-- Add new releases here -->
<release version="{new_version}" date="{now:%Y-%m-%d}"/>
[bumpversion:file:doc/changelog.asciidoc]
search = (unreleased)
replace = ({now:%Y-%m-%d})

26
.bumpversion.toml Normal file
View File

@ -0,0 +1,26 @@
[tool.bumpversion]
current_version = "3.6.3"
commit = true
message = "Release v{new_version}"
tag = true
sign_tags = true
tag_name = "v{new_version}"
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
serialize = ["{major}.{minor}.{patch}"]
allow_dirty = false
[[tool.bumpversion.files]]
filename = "qutebrowser/__init__.py"
search = "__version__ = \"{current_version}\""
replace = "__version__ = \"{new_version}\""
[[tool.bumpversion.files]]
filename = "misc/org.qutebrowser.qutebrowser.appdata.xml"
search = "<!-- Add new releases here -->"
replace = """<!-- Add new releases here -->
<release version='{new_version}' date='{now:%Y-%m-%d}'/>"""
[[tool.bumpversion.files]]
filename = "doc/changelog.asciidoc"
search = "(unreleased)"
replace = "({now:%Y-%m-%d})"

View File

@ -4,6 +4,7 @@ include =
tests/*
scripts/*
branch = true
patch = subprocess
omit =
qutebrowser/__main__.py
*/__init__.py

View File

@ -42,6 +42,7 @@ exclude = .*,__pycache__,resources.py
# W503: like break before binary operator
# W504: line break after binary operator
# FI18: __future__ import "annotations" missing
# FI58: __future__ import "annotations" present
# PT004: fixture '{name}' does not return anything, add leading underscore
# PT011: pytest.raises(ValueError) is too broad, set the match parameter or use a more specific exception
# PT012: pytest.raises() block should contain a single simple statement
@ -54,11 +55,11 @@ ignore =
D102,D103,D106,D107,D104,D105,D209,D211,D401,D402,D403,D412,D413,
A003,
W503, W504,
FI18,
FI18,FI58,
PT004,
PT011,
PT012
min-version = 3.8.0
min-version = 3.9.0
max-complexity = 12
per-file-ignores =
qutebrowser/api/hook.py : N801

View File

@ -10,15 +10,13 @@ on:
jobs:
tests:
if: "github.repository == 'qutebrowser/qutebrowser'"
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
include:
- testenv: bleeding
image: "archlinux-webengine-unstable-qt6"
- testenv: bleeding-qt5
image: "archlinux-webengine-unstable"
container:
image: "qutebrowser/ci:${{ matrix.image }}"
@ -33,14 +31,13 @@ jobs:
- /home/runner/work/_temp/:/home/runner/work/_temp/
options: --privileged --tty
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: Set up problem matchers
run: "python scripts/dev/ci/problemmatchers.py py3 ${{ runner.temp }}"
- name: Upgrade 3rd party assets
run: "tox exec -e ${{ matrix.testenv }} -- python scripts/dev/update_3rdparty.py --gh-token ${{ secrets.GITHUB_TOKEN }}"
if: "endsWith(matrix.image, '-qt6')"
run: "tox exec -e ${{ matrix.testenv }} -- python scripts/dev/update_3rdparty.py --gh-token ${{ secrets.GITHUB_TOKEN }} --modern-pdfjs"
- name: Run tox
run: dbus-run-session tox -e ${{ matrix.testenv }}
- name: Gather info
@ -51,7 +48,7 @@ jobs:
shell: bash
if: failure()
- name: Upload screenshots
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: "end2end-screenshots-${{ steps.info.outputs.date }}-${{ steps.info.outputs.sha_short }}-${{ matrix.image }}"
path: |
@ -61,7 +58,7 @@ jobs:
irc:
timeout-minutes: 2
continue-on-error: true
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
needs: [tests]
if: "always() && github.repository == 'qutebrowser/qutebrowser'"
steps:

View File

@ -14,7 +14,7 @@ jobs:
linters:
if: "!contains(github.event.head_commit.message, '[ci skip]')"
timeout-minutes: 10
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
@ -27,7 +27,6 @@ jobs:
- testenv: vulture
- testenv: misc
- testenv: pyroma
- testenv: check-manifest
- testenv: eslint
- testenv: shellcheck
args: "-f gcc" # For problem matchers
@ -35,30 +34,30 @@ jobs:
- testenv: actionlint
- testenv: package
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: actions/cache@v4
- uses: actions/cache@v5
with:
path: |
.mypy_cache
.tox
~/.cache/pip
key: "${{ matrix.testenv }}-${{ hashFiles('misc/requirements/requirements-*.txt') }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('scripts/dev/pylint_checkers/qute_pylint/*.py') }}"
- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: '3.10'
- uses: actions/setup-node@v4
- uses: actions/setup-node@v6
with:
node-version: '16.x'
node-version: '22.x'
if: "matrix.testenv == 'eslint'"
- name: Set up problem matchers
run: "python scripts/dev/ci/problemmatchers.py ${{ matrix.testenv }} ${{ runner.temp }}"
- name: Install dependencies
run: |
[[ ${{ matrix.testenv }} == eslint ]] && npm install -g 'eslint@<9.0.0'
[[ ${{ matrix.testenv }} == docs ]] && sudo apt-get update && sudo apt-get install --no-install-recommends asciidoc libegl1-mesa
[[ ${{ matrix.testenv }} == vulture || ${{ matrix.testenv }} == pylint ]] && sudo apt-get update && sudo apt-get install --no-install-recommends libegl1-mesa
[[ ${{ matrix.testenv }} == docs ]] && sudo apt-get update && sudo apt-get install --no-install-recommends asciidoc libegl1
[[ ${{ matrix.testenv }} == vulture || ${{ matrix.testenv }} == pylint ]] && sudo apt-get update && sudo apt-get install --no-install-recommends libegl1
if [[ ${{ matrix.testenv }} == shellcheck ]]; then
scversion="stable"
bindir="$HOME/.local/bin"
@ -86,21 +85,15 @@ jobs:
tests-docker:
if: "!contains(github.event.head_commit.message, '[ci skip]')"
timeout-minutes: 45
runs-on: ubuntu-22.04
runs-on: ubuntu-22.04 # not 24.04 because sandboxing fails by default (#8424)
strategy:
fail-fast: false
matrix:
include:
- testenv: py-qt5
image: archlinux-webkit
- testenv: py-qt5
- testenv: py
image: archlinux-webengine
- testenv: py-qt5
- testenv: py
image: archlinux-webengine-unstable
- testenv: py
image: archlinux-webengine-qt6
- testenv: py
image: archlinux-webengine-unstable-qt6
container:
image: "qutebrowser/ci:${{ matrix.image }}"
env:
@ -113,7 +106,7 @@ jobs:
- /home/runner/work/_temp/:/home/runner/work/_temp/
options: --privileged --tty
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: Set up problem matchers
@ -128,7 +121,7 @@ jobs:
shell: bash
if: failure()
- name: Upload screenshots
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: "end2end-screenshots-${{ steps.info.outputs.date }}-${{ steps.info.outputs.sha_short }}-${{ matrix.image }}"
path: |
@ -144,10 +137,10 @@ jobs:
fail-fast: false
matrix:
include:
### PyQt 5.15.2 (Python 3.8)
- testenv: py38-pyqt5152
os: ubuntu-20.04
python: "3.8"
### PyQt 5.15.2 (Python 3.9)
- testenv: py39-pyqt5152
os: ubuntu-22.04
python: "3.9"
### PyQt 5.15 (Python 3.10, with coverage)
# FIXME:qt6
# - testenv: py310-pyqt515-cov
@ -155,19 +148,19 @@ jobs:
# python: "3.10"
### PyQt 5.15 (Python 3.11)
- testenv: py311-pyqt515
os: ubuntu-20.04
os: ubuntu-22.04
python: "3.11"
### PyQt 6.2 (Python 3.8)
- testenv: py38-pyqt62
os: ubuntu-20.04
python: "3.8"
### PyQt 6.3 (Python 3.8)
- testenv: py38-pyqt63
os: ubuntu-20.04
python: "3.8"
### PyQt 6.2 (Python 3.9)
- testenv: py39-pyqt62
os: ubuntu-22.04
python: "3.9"
### PyQt 6.3 (Python 3.9)
- testenv: py39-pyqt63
os: ubuntu-22.04
python: "3.9"
## PyQt 6.4 (Python 3.9)
- testenv: py39-pyqt64
os: ubuntu-20.04
os: ubuntu-22.04
python: "3.9"
### PyQt 6.5 (Python 3.10)
- testenv: py310-pyqt65
@ -189,31 +182,45 @@ jobs:
- testenv: py312-pyqt67
os: ubuntu-22.04
python: "3.12"
### macOS Monterey
- testenv: py312-pyqt67
os: macos-12
python: "3.12"
args: "tests/unit" # Only run unit tests on macOS
### macOS Ventura
- testenv: py312-pyqt67
os: macos-13
python: "3.12"
args: "tests/unit" # Only run unit tests on macOS
### PyQt 6.8 (Python 3.13)
- testenv: py313-pyqt68
os: ubuntu-24.04
python: "3.13"
### PyQt 6.8 (Python 3.13)
- testenv: py313-pyqt68
os: ubuntu-24.04
python: "3.13"
### PyQt 6.9 (Python 3.14)
- testenv: py314-pyqt69
os: ubuntu-24.04
python: "3.14"
### PyQt 6.10 (Python 3.14)
- testenv: py314-pyqt610
os: ubuntu-24.04
python: "3.14"
### macOS Sonoma (M1 runner)
- testenv: py312-pyqt67
- testenv: py314-pyqt610
os: macos-14
python: "3.12"
python: "3.14"
args: "tests/unit" # Only run unit tests on macOS
### macOS Sequoia (Intel runner)
- testenv: py314-pyqt610
os: macos-15-intel
python: "3.14"
args: "tests/unit" # Only run unit tests on macOS
### Windows
- testenv: py312-pyqt67
os: windows-2019
python: "3.12"
- testenv: py314-pyqt610
os: windows-2022
python: "3.14"
- testenv: py314-pyqt610
os: windows-2025
python: "3.14"
runs-on: "${{ matrix.os }}"
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: actions/cache@v4
- uses: actions/cache@v5
with:
path: |
.mypy_cache
@ -221,7 +228,7 @@ jobs:
~/.cache/pip
key: "${{ matrix.testenv }}-${{ matrix.os }}-${{ matrix.python }}-${{ hashFiles('misc/requirements/requirements-*.txt') }}-${{ hashFiles('requirements.txt') }}"
- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "${{ matrix.python }}"
- name: Set up problem matchers
@ -229,7 +236,7 @@ jobs:
- name: Install apt dependencies
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends libyaml-dev libegl1-mesa libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-shape0 libxcb-cursor0
sudo apt-get install --no-install-recommends libyaml-dev libegl1 libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-shape0 libxcb-cursor0 libjpeg-dev
if: "startsWith(matrix.os, 'ubuntu-')"
- name: Install dependencies
run: |
@ -251,7 +258,7 @@ jobs:
if: "failure()"
- name: Upload coverage
if: "endsWith(matrix.testenv, '-cov')"
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v5
with:
name: "${{ matrix.testenv }}"
- name: Gather info
@ -262,7 +269,7 @@ jobs:
shell: bash
if: failure()
- name: Upload screenshots
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: "end2end-screenshots-${{ steps.info.outputs.date }}-${{ steps.info.outputs.sha_short }}-${{ matrix.testenv }}-${{ matrix.os }}"
path: |
@ -275,24 +282,24 @@ jobs:
permissions:
security-events: write
timeout-minutes: 15
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
with:
languages: javascript, python
queries: +security-extended
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4
irc:
timeout-minutes: 2
continue-on-error: true
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs: [linters, tests, tests-docker, codeql]
if: "always() && github.repository_owner == 'qutebrowser'"
steps:

View File

@ -8,19 +8,16 @@ on:
jobs:
docker:
if: "github.repository == 'qutebrowser/qutebrowser'"
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
image:
- archlinux-webkit
- archlinux-webengine
- archlinux-webengine-unstable
- archlinux-webengine-unstable-qt6
- archlinux-webengine-qt6
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: '3.x'
- run: pip install jinja2
@ -42,7 +39,7 @@ jobs:
irc:
timeout-minutes: 2
continue-on-error: true
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
needs: [docker]
if: "always() && github.repository == 'qutebrowser/qutebrowser'"
steps:

View File

@ -14,50 +14,45 @@ jobs:
fail-fast: false
matrix:
include:
- os: macos-12
toxenv: build-release-qt5
name: qt5-macos
- os: windows-2019
toxenv: build-release-qt5
name: qt5-windows
- os: macos-12
args: --debug
toxenv: build-release-qt5
name: qt5-macos-debug
- os: windows-2019
args: --debug
toxenv: build-release-qt5
name: qt5-windows-debug
- os: macos-12
- os: macos-15-intel
toxenv: build-release
name: macos-intel
- os: macos-14
toxenv: build-release
name: macos-apple-silicon
- os: windows-2019
- os: windows-latest
toxenv: build-release
name: windows
- os: macos-12
- os: macos-15-intel
args: --debug
toxenv: build-release
name: macos-debug-intel
- os: macos-14
toxenv: build-release
name: macos-debug-apple-silicon
- os: windows-2019
- os: windows-latest
args: --debug
toxenv: build-release
name: windows-debug
runs-on: "${{ matrix.os }}"
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.10"
python-version: "3.13"
- name: Install nsis
if: "matrix.os == 'windows-latest'"
run: |
irm get.scoop.sh | iex
scoop update
scoop bucket add extras
scoop install nsis
Add-Content $env:GITHUB_PATH "C:\Users\runneradmin\scoop\shims"
shell: pwsh
- name: Install dependencies
run: |
python -m pip install -U pip
@ -77,7 +72,7 @@ jobs:
echo "sha_short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
shell: bash
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: "qutebrowser-nightly-${{ steps.info.outputs.date }}-${{ steps.info.outputs.sha_short }}-${{ matrix.name }}"
path: |
@ -89,7 +84,7 @@ jobs:
irc:
timeout-minutes: 2
continue-on-error: true
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
needs: [pyinstaller]
if: "always() && github.repository == 'qutebrowser/qutebrowser'"
steps:

View File

@ -18,20 +18,20 @@ jobs:
timeout-minutes: 20
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: Set up Python 3.8
uses: actions/setup-python@v5
- name: Set up Python 3.9
uses: actions/setup-python@v6
with:
python-version: '3.8'
python-version: '3.9'
- name: Recompile requirements
run: "python3 scripts/dev/recompile_requirements.py ${{ github.event.input.environments }}"
id: requirements
- name: Install apt dependencies
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends libyaml-dev libegl1-mesa libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-shape0 libxcb-cursor0 asciidoc python3-venv xvfb
sudo apt-get install --no-install-recommends libyaml-dev libegl1 libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-shape0 libxcb-cursor0 asciidoc python3-venv xvfb
- name: Install dependencies
run: |
python -m pip install -U pip
@ -41,7 +41,7 @@ jobs:
- name: Run qutebrowser smoke test
run: "xvfb-run .venv/bin/python3 -m qutebrowser --no-err-windows --nowindow --temp-basedir about:blank ':later 500 quit'"
- name: Create pull request
uses: peter-evans/create-pull-request@v6
uses: peter-evans/create-pull-request@v8
with:
committer: qutebrowser bot <bot@qutebrowser.org>
author: qutebrowser bot <bot@qutebrowser.org>

View File

@ -12,30 +12,33 @@ on:
- 'patch'
- 'minor'
- 'major'
- 'reupload' # reupload last release
# FIXME do we want a possibility to do prereleases here?
python_version:
description: 'Python version'
required: true
default: '3.12'
default: '3.14'
type: choice
options:
- '3.8'
- '3.9'
- '3.10'
- '3.11'
- '3.12'
- '3.13'
- '3.14'
jobs:
prepare:
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
timeout-minutes: 5
outputs:
version: ${{ steps.bump.outputs.version }}
release_id: ${{ steps.create-release.outputs.id }}
version_x: ${{ steps.bump.outputs.version_x }}
release_id: ${{ inputs.release_type == 'reupload' && steps.find-release.outputs.result || steps.create-release.outputs.id }}
permissions:
contents: write # To push release commit/tag
steps:
- name: Find release branch
uses: actions/github-script@v7
uses: actions/github-script@v8
id: find-branch
with:
script: |
@ -59,9 +62,9 @@ jobs:
console.log(`sorted: ${sorted}`);
return sorted.at(-1);
result-encoding: string
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
# Doesn't really matter what we prepare the release with, but let's
# use the same version for consistency.
@ -75,7 +78,7 @@ jobs:
git config --global user.name "qutebrowser bot"
git config --global user.email "bot@qutebrowser.org"
- name: Switch to release branch
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
ref: ${{ steps.find-branch.outputs.result }}
- name: Import GPG Key
@ -83,9 +86,9 @@ jobs:
gpg --import <<< "${{ secrets.QUTEBROWSER_BOT_GPGKEY }}"
- name: Bump version
id: bump
run: "tox -e update-version -- ${{ github.event.inputs.release_type }}"
run: "tox -e update-version -- ${{ inputs.release_type }}"
- name: Check milestone
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
const milestones = await github.paginate(github.rest.issues.listMilestones, {
@ -100,49 +103,74 @@ jobs:
core.setFailed(`Found open milestone ${milestone.title} with ${milestone.open_issues} open and ${milestone.closed_issues} closed issues!`);
}
- name: Push release commit/tag
if: ${{ inputs.release_type != 'reupload' }}
run: |
git push origin ${{ steps.find-branch.outputs.result }}
git push origin v${{ steps.bump.outputs.version }}
- name: Cherry-pick release commit
if: ${{ github.event.inputs.release_type == 'patch' }}
if: ${{ inputs.release_type == 'patch' }}
run: |
git fetch origin main
git checkout main
git cherry-pick -x v${{ steps.bump.outputs.version }}
git push origin main
git checkout v${{ steps.bump.outputs.version_x }}
- name: Create release branch
if: ${{ github.event.inputs.release_type != 'patch' }}
if: ${{ inputs.release_type == 'minor' || inputs.release_type == 'major' }}
run: |
git checkout -b v${{ steps.bump.outputs.version_x }}
git push --set-upstream origin v${{ steps.bump.outputs.version_x }}
- name: Create GitHub draft release
if: ${{ inputs.release_type != 'reupload' }}
id: create-release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.bump.outputs.version }}
draft: true
body: "*Release artifacts for this release are currently being uploaded...*"
- name: Find GitHub draft release
if: ${{ inputs.release_type == 'reupload' }}
id: find-release
uses: actions/github-script@v8
with:
script: |
const releases = await github.paginate(github.rest.repos.listReleases, {
owner: context.repo.owner,
repo: context.repo.repo,
});
const names = releases.map(release => release.name);
console.log(`releases: ${names}`);
const release = releases.find(release => release.tag_name === "v${{ steps.bump.outputs.version }}");
if (release === undefined) {
core.setFailed(`No release found with tag v${{ steps.bump.outputs.version }}!`);
}
if (!release.draft) {
core.setFailed(`Release ${release.tag_name} is not a draft release!`);
}
return release.id;
result-encoding: string
release:
strategy:
matrix:
include:
- os: macos-12
- os: macos-14
- os: windows-2019
- os: ubuntu-20.04
- os: macos-14-large # Intel
- os: macos-14 # Apple Silicon
- os: windows-2022
- os: ubuntu-24.04
runs-on: "${{ matrix.os }}"
timeout-minutes: 45
needs: [prepare]
permissions:
contents: write # To upload release artifacts
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
ref: v${{ needs.prepare.outputs.version }}
ref: v${{ inputs.release_type == 'reupload' && needs.prepare.outputs.version_x || needs.prepare.outputs.version }}
- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: ${{ github.event.inputs.python_version }}
python-version: ${{ inputs.python_version }}
- name: Import GPG Key
if: ${{ startsWith(matrix.os, 'ubuntu-') }}
run: |
@ -159,7 +187,7 @@ jobs:
if: ${{ startsWith(matrix.os, 'ubuntu-') }}
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends libegl1-mesa libxml2-utils docbook-xml xsltproc docbook-xsl
sudo apt-get install --no-install-recommends libegl1 libxml2-utils docbook-xml xsltproc docbook-xsl
- name: Install dependencies
run: |
python -m pip install -U pip
@ -167,20 +195,20 @@ jobs:
# FIXME consider switching to trusted publishers:
# https://blog.pypi.org/posts/2023-04-20-introducing-trusted-publishers/
- name: Build and upload release
run: "tox -e build-release -- --upload --no-confirm"
run: "tox -e build-release -- --upload --no-confirm ${{ inputs.release_type == 'reupload' && '--reupload' || '' }}"
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.QUTEBROWSER_BOT_PYPI_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
finalize:
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
timeout-minutes: 5
needs: [prepare, release]
permissions:
contents: write # To change release
steps:
- name: Publish final release
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
await github.rest.repos.updateRelease({
@ -193,7 +221,7 @@ jobs:
irc:
timeout-minutes: 2
continue-on-error: true
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
needs: [prepare, release, finalize]
if: "${{ always() }}"
steps:

View File

@ -1,5 +1,5 @@
[mypy]
python_version = 3.8
python_version = 3.9
### --strict
warn_unused_configs = True
@ -20,6 +20,7 @@ strict_equality = True
warn_unreachable = True
disallow_any_unimported = True
enable_error_code = ignore-without-code
strict_bytes = True
### Output
show_error_context = True

View File

@ -16,7 +16,7 @@ load-plugins=qute_pylint.config,
pylint.extensions.dunder
persistent=n
py-version=3.8
py-version=3.9
[MESSAGES CONTROL]
enable=all
@ -71,7 +71,8 @@ argument-rgx=[a-z_][a-z0-9_]{0,30}$
variable-rgx=[a-z_][a-z0-9_]{0,30}$
docstring-min-length=3
no-docstring-rgx=(^_|^main$)
class-const-naming-style = snake_case
class-const-naming-style=snake_case
max-positional-arguments=7
[FORMAT]
# FIXME:v4 (lint) down to 88 again once we use black

View File

@ -44,7 +44,7 @@ image:doc/img/hints.png["screenshot 4",width=300,link="doc/img/hints.png"]
Downloads
---------
See the https://github.com/qutebrowser/qutebrowser/releases[github releases
See the https://github.com/qutebrowser/qutebrowser/releases[GitHub releases
page] for available downloads and the link:doc/install.asciidoc[INSTALL] file for
detailed instructions on how to get qutebrowser running on various platforms.
@ -84,7 +84,7 @@ Requirements
The following software and libraries are required to run qutebrowser:
* https://www.python.org/[Python] 3.8 or newer
* https://www.python.org/[Python] 3.9 or newer
* https://www.qt.io/[Qt], either 6.2.0 or newer, or 5.15.0 or newer, with the following modules:
- QtCore / qtbase
- QtQuick (part of qtbase or qtdeclarative in some distributions)
@ -105,10 +105,6 @@ websites and using it for transmission of sensitive data._
* https://palletsprojects.com/p/jinja/[jinja2]
* https://github.com/yaml/pyyaml[PyYAML]
On Python 3.8, the following backport is also required:
* https://importlib-resources.readthedocs.io/[importlib_resources]
On macOS, the following libraries are also required:
* https://pyobjc.readthedocs.io/en/latest/[pyobjc-core and pyobjc-framework-Cocoa]

View File

@ -15,6 +15,279 @@ 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.
[[v3.6.4]]
v3.6.4 (unreleased)
-------------------
Fixed
~~~~~
- datalist dropdowns not opening correctly on Wayland/Sway (#8831).
This was caused by an old workaround for a different QtWebEngine issue,
which is now disabled for QtWebEngine 6.6.3 and newer.
[[v3.6.3]]
v3.6.3 (2025-11-30)
-------------------
Fixed
~~~~~
- New `qt.workarounds.disable_accessibility` setting, which disables Chromium
accessibility support. By default, is it set to `auto`, which only disables
accessibility on Qt versions with known issues. This works around a bug in Qt
6.10.1 causing frequent segfaults (#8797).
[[v3.6.2]]
v3.6.2 (2025-11-27)
-------------------
Changed
~~~~~~~
* Windows and macOS releases now ship with Qt 6.10.1, which include
security patches up to Chromium 142.0.7444.162.
Fixed
~~~~~
- The version info now includes the Wayland compositor name if wayland-client is
available under a different name than `libwayland-client.so` (#8771).
- The list of Chromium extensions in `--version` / `:version` now uses the
correct Chromium data profile, also fixing a crash with Qt 6.10.1 (#8785).
- With Qt 6.10.1, `qt.workarounds.disable_hangouts_extension` now doesn't apply
on private profiles, avoiding a Qt bug leading to a crash (#8785).
[[v3.6.1]]
v3.6.1 (2025-11-03)
-------------------
Fixed
~~~~~
- A regression in v3.6.0 where the page didn't have keyboard focus after closing
the completion, so e.g. typing in an input field after hinting didn't work.
(#8750)
[[v3.6.0]]
v3.6.0 (2025-10-24)
-------------------
Added
~~~~~
- The `:version` info now shows additional information:
* The X11 window manager / Wayland compositor name (mostly useful for
bug/crash reports).
* Loaded WebExtensions (partial support landed in QtWebEngine 6.10, no
official qutebrowser support yet).
- Support for hinting elements which are part of an (open) shadow DOM.
Changed
~~~~~~~
- The `qutedmenu` userscript now sorts history by the last access time.
- Hardware accelerated 2D canvas is now enabled by default on Qt 6.8.2+,
as graphic glitches with e.g. PDF.js and Google Sheets should be fixed
nowadays. If you still run into issues, please report them and set
`qt.workarounds.disable_accelerated_2d_canvas` to `always` to disable it
again.
- Changes to binary releases:
* Windows and macOS releases are now built with Qt 6.10.0, which is based
on Chromium 134.0.6998.208 with security patches up to 140.0.7339.207.
* Windows and macOS releases are now built with Python 3.14.
* Windows releases are now built on Windows Server 2022 (previously 2019),
which might break compatibility with older Windows releases (untested).
* If using `mkvenv.py` on Linux, note that Qt now requires glibc v2.34 (v2.28
previously). This is available down to Ubuntu 22.04 LTS and Debian Bookworm
(oldstable), so this should not affect most users of desktop distributions.
Fixed
~~~~~
- Fixed crash if two new downloads start while a download prompt is already open
(#8674).
- Fixed exception when closing a qutebrowser window while a download prompt is
still open.
- Hopefully proper fix for some web pages jumping to the top when the statusbar
is hidden (#8223).
- Fix for the page header being shown on YouTube after the fullscreen
notification was hidden (#8625).
- Fix for videos losing keyboard focus when the fullscreen notification shows
(#8174).
- The workaround for microphone/camera permissions not being requested with
QtWebEngine 6.9 on Google Meet, Zoom, or other pages using the new
`<permission>` element now got extended to Qt 6.9.1+ as it's still not fixed
upstream. (#8612)
- The package version for Jinja 3.3+ is now correctly displayed in `:version`.
- Fixed crash with Qt 6.10 (and possibly older Qt versions) when navigating
from a `qute://` page to a web page, e.g. when searching on `qute://start`.
- On Wayland with Qt <= 6.9, `EGL_PLATFORM=wayland` is now set by qutebrowser to
get hardware rendering. Qt 6.10 includes an equivalent fix (#8637).
- Added workaround for per-domain User-Agent header not being used on redirects
(#8679).
- Added site-specific quirk for gitlab.gnome.org agressively blocking old
Chromium versions (and thus QtWebEngine) (#8509).
- Using `:config-list-remove` with an invalid value for the respective option
type now corrently displays an error instead of crashing.
[[v3.5.1]]
v3.5.1 (2025-06-05)
-------------------
Deprecated
~~~~~~~~~~
- QtWebKit (legacy) support got removed from CI and is now untested. If it
breaks, it's not going to be fixed, and support will be removed over the next
releases.
- Qt 5 support is currently still tested, but is also planned to get removed
over the next releases. Same goes for support for older Qt 6 versions (likely
6.2/6.3/6.4 and perhaps 6.5, see https://github.com/qutebrowser/qutebrowser/issues/8464[#8464]).
Changed
~~~~~~~
- Windows/macOS releases now bundle Qt 6.9.1, including many graphics-related
bugfixes, as well as security patches up to Chromium 136.0.7103.114.
Fixed
~~~~~
- A bogus "wildcard call disconnects from destroyed signal" warning from Qt is
now suppressed.
- PDF.js now loads correctly on Windows installations with broken mimetype
configurations.
- A "Ignoring new child ..." debug log message which got spammy with Qt 6.9 is
now removed.
- A unknown crash (possibly related to using devtools) due to weird (Py)Qt
behavior now has a workaround.
- No "QtWebEngine version mismatch" warning is now logged anymore with newer Qt
5.15 releases (but you should still stop using Qt 5).
- The PDF.js version can now correctly be extracted/displayed with newer PDF.js
versions.
- The `qute-bitwarden`, `-lastpass` and `-pass` userscripts now properly avoid
a `DeprecationWarning` from the upcoming 6.0 release of `tldextract`. The
previous fix in v3.5.1 was insufficient.
[[v3.5.0]]
v3.5.0 (2025-04-12)
-------------------
Changed
~~~~~~~
- Windows/macOS releases are now built with Qt 6.9.0
* Based on Chromium 130.0.6723.192
* Security fixes up to Chromium 133.0.6943.141
* Also fixes issues with opening links on macOS
- The `content.headers.user_agent` setting now has a new
`{upstream_browser_version_short}` template field, which is the
upstream/Chromium version but shortened to only major version.
- The default user agent now uses the shortened Chromium version and doesn't
expose the `QtWebEngine/...` part anymore, thus making it equal to the
corresponding Chromium user agent. This increases compatibilty due to various
overzealous "security" products used by a variety of websites that block
QtWebEngine, presumably as a bot (known issues existed with Whatsapp Web, UPS,
Digitec Galaxus).
- Changed features in userscripts:
* `qute-bitwarden` now passes your password to the subprocess in an
environment variable when unlocking your vault, instead of as a command
line argument. (#7781)
- New `-D no-system-pdfjs` debug flag to ignore system-wide PDF.js installations
for testing.
- Polyfill for missing `URL.parse` with PDF.js v5 and QtWebEngine < 6.9. Note
this is a "best effort" fix and you should be using the "older browsers"
("legacy") build of PDF.js instead.
Removed
~~~~~~~
- The `ua-slack` site-specific quirk, as things seem to work better nowadays
without a quirk needed.
- The `ua-whatsapp` site-specific quirk, as it's unneeded with the default UA
change described above.
Fixed
~~~~~
- Crash when trying to use the `DocumentPictureInPicture` JS API, such as done
by the new Google Workspaces Huddle feature. The API is unsupported by
QtWebEngine and now correctly disabled on the JS side. (#8449)
- Crash when a buggy notification presenter returns a duplicate ID (now an
error is shown instead).
- Crashes when running `:tab-move` or `:yank title` at startup, before a tab is
available.
- Crash with `input.insert_mode.auto_load`, when closing a new tab quickly after
opening it, but before it was fully loaded. (#3895, #8400)
- Workaround for microphone/camera permissions not being requested with
QtWebEngine 6.9.0 on Google Meet, Zoom, or other pages using the new
`<permission>` element. (#8539)
- Resolved issues in userscripts:
* `qute-bitwarden` will now prompt a re-login if its cached session has
been invalidated since last used. (#8456)
* `qute-bitwarden`, `-lastpass` and `-pass` now avoid a
`DeprecationWarning` from the upcoming 6.0 release of `tldextract`
[[v3.4.0]]
v3.4.0 (2024-12-14)
-------------------
Removed
~~~~~~~
- Support for Python 3.8 is dropped, and Python 3.9 is now required. (#8325)
- Support for macOS 12 Monterey is now dropped, and binaries will be built on
macOS 13 Ventura. (#8327)
- When using the installer on Windows 10, build 1809 or newer is now required
(previous versions required 1607 or newer, but that's not officialy supported by
Qt upstream). (#8336)
Changed
~~~~~~~
- Windows/macOS binaries are now built with Qt 6.8.1. (#8242)
- Based on Chromium 122.0.6261.171
- With security patches up to 131.0.6778.70
- Windows/macOS binaries are now using Python 3.13. (#8205)
- The `.desktop` file now also declares qutebrowser as a valid viewer for
`image/webp`. (#8340)
- Updated mimetype information for getting a suitable extension when downloading
a `data:` URL.
- The `content.javascript.clipboard` setting now defaults to "ask", which on
Qt 6.8+ will prompt the user to grant clipboard access. On older Qt versions,
this is still equivalent to `"none"` and needs to be set manually. (#8348)
- If a XHR request made via JS sets a custom `Accept-Language` header, it now
correctly has precedence over the global `content.headers.accept_language`
setting (but not per-domain overrides). This fixes subtle JS issues on
websites that rely on the custom header being sent for those requests, and
e.g. block the requests server-side otherwise. (#8370)
- Our packaging scripts now prefer the "legacy"/"for older browsers" PDF.js
build as their normal release only supports the latest Chromium version and
might break in qutebrowser on updates. **Note to packagers:** If there's a
PDF.js package in your distribution as an (optional) qutebrowser dependency,
consider also switching to this variant (same code, built differently).
Fixed
~~~~~
- Crash with recent Jinja/Markupsafe versions when viewing a finished userscript
(or potentially editor) process via `:process`.
- `scripts/open_url_in_instance.sh` now avoids `echo -n`, thus running
correctly on POSIX sh. (#8409)
- Added a workaround for a bogus QtWebEngine warning about missing spell
checking dictionaries. (#8330)
[[v3.3.1]]
v3.3.1 (2024-10-12)
-------------------
Fixed
~~~~~
- Updated the workaround for Google sign-in issues.
[[v3.3.0]]
v3.3.0 (2024-10-12)
-------------------
@ -24,16 +297,16 @@ Added
- Added the `qt.workarounds.disable_hangouts_extension` setting,
for disabling the Google Hangouts extension built into Chromium/QtWebEngine.
- Failed end2end tests will now save screenshots of the browser window when
run under xvfb (the default on linux). Screenshots will be under
`$TEMP/pytest-current/pytest-screenshots/` or attached to the GitHub actions
run as an artifact. (#7625)
Removed
~~~~~~~
- Support for macOS 11 Big Sur is dropped. Binaries are now built on macOS 12
Monterey and are unlikely to still run on older macOS versions.
- Failed end2end tests will now save screenshots of the browser window when
run under xvfb (the default on linux). Screenshots will be under
`$TEMP/pytest-current/pytest-screenshots/` or attached to the GitHub actions
run as an artifact. (#7625)
Changed
~~~~~~~
@ -45,6 +318,8 @@ Changed
respected when yanking any URL (for example, through hints with `hint links
yank`). The `{url:yank}` substitution has also been added as a version of
`{url}` that respects ignored URL query parameters. (#7879)
- Windows and macOS releases now bundle Qt 6.7.3, which includes security fixes
up to Chromium 129.0.6668.58.
Fixed
~~~~~
@ -55,6 +330,7 @@ Fixed
documentation in our settings docs now loads a live page again. (#8268)
- A rare crash when on Qt 6, a renderer process terminates with an unknown
termination reason.
- Updated the workaround for Google sign-in issues.
[[v3.2.1]]
v3.2.1 (2024-06-25)

View File

@ -41,7 +41,7 @@ If you want to find something useful to do, check the
https://github.com/qutebrowser/qutebrowser/issues[issue tracker]. Some
pointers:
* https://github.com/qutebrowser/qutebrowser/labels/easy[Issues which should
* https://github.com/qutebrowser/qutebrowser/contribute[Issues which should
be easy to solve]
* https://github.com/qutebrowser/qutebrowser/labels/component%3A%20docs[Documentation issues which require little/no coding]
@ -111,9 +111,9 @@ unittests and several linters/checkers.
Currently, the following tox environments are available:
* Tests using https://www.pytest.org[pytest]:
- `py38`, `py39`, ...: Run pytest for python 3.8/3.9/... with the system-wide PyQt.
- `py38-pyqt515`, ..., `py38-pyqt65`: Run pytest with the given PyQt version (`py39-*` etc. also works).
- `py38-pyqt515-cov`: Run with coverage support (other Python/PyQt versions work too).
- `py39`, `py310`, ...: Run pytest for python 3.9/3.10/... with the system-wide PyQt.
- `py39-pyqt515`, ..., `py39-pyqt65`: Run pytest with the given PyQt version (`py310-*` etc. also works).
- `py39-pyqt515-cov`: Run with coverage support (other Python/PyQt versions work too).
* `flake8`: Run various linting checks via https://pypi.python.org/pypi/flake8[flake8].
* `vulture`: Run https://pypi.python.org/pypi/vulture[vulture] to find
unused code portions.
@ -121,8 +121,6 @@ Currently, the following tox environments are available:
* `pyroma`: Check packaging practices with
https://pypi.python.org/pypi/pyroma/[pyroma].
* `eslint`: Run https://eslint.org/[ESLint] javascript checker.
* `check-manifest`: Check MANIFEST.in completeness with
https://github.com/mgedmin/check-manifest[check-manifest].
* `mkvenv`: Bootstrap a virtualenv for testing.
* `misc`: Run `scripts/misc_checks.py` to check for:
- untracked git files
@ -171,16 +169,16 @@ Examples:
----
# run only pytest tests which failed in last run:
tox -e py38 -- --lf
tox -e py39 -- --lf
# run only the end2end feature tests:
tox -e py38 -- tests/end2end/features
tox -e py39 -- tests/end2end/features
# run everything with undo in the generated name, based on the scenario text
tox -e py38 -- tests/end2end/features/test_tabs_bdd.py -k undo
tox -e py39 -- tests/end2end/features/test_tabs_bdd.py -k undo
# run coverage test for specific file (updates htmlcov/index.html)
tox -e py38-cov -- tests/unit/browser/test_webelem.py
tox -e py39-cov -- tests/unit/browser/test_webelem.py
----
Specifying the backend for tests
@ -604,6 +602,7 @@ Info pages:
- chrome://device-log/ (QtWebEngine >= 6.3)
- chrome://gpu/
- chrome://sandbox/ (Linux only)
- chrome://qt/ (QtWebEngine >= 6.7)
Misc. / Debugging pages:
@ -614,6 +613,7 @@ Misc. / Debugging pages:
- chrome://ukm/ (QtWebEngine >= 5.15.3)
- chrome://user-actions/ (QtWebEngine >= 5.15.3)
- chrome://webrtc-logs/ (QtWebEngine >= 5.15.3)
- chrome://extensions/ (QtWebEngine >= 6.10)
Internals pages:
@ -789,10 +789,12 @@ New PyQt release
qutebrowser release
~~~~~~~~~~~~~~~~~~~
* Make sure there are no unstaged changes and the tests are green.
* Make sure there are no unstaged or unpushed changes.
* Make sure CI is reasonably green.
* Make sure all issues with the related milestone are closed.
* Mark the https://github.com/qutebrowser/qutebrowser/milestones[milestone] as closed.
* Consider updating the completions for `content.headers.user_agent` in `configdata.yml`.
* Consider updating the completions for `content.headers.user_agent` in `configdata.yml`
and the Firefox UA in `qutebrowser/browser/webengine/webenginesettings.py`.
* Minor release: Consider updating some files from main:
- `misc/requirements/` and `requirements.txt`
- `scripts/`
@ -802,7 +804,8 @@ qutebrowser release
**Automatic release via GitHub Actions (starting with v3.0.0):**
* Double check Python version in `.github/workflows/release.yml`
* Run the `release` workflow on the `main` branch, e.g. via `gh workflow run release -f release_type=major` (`release_type` can be `major`, `minor` or `patch`; you can also override `python_version`)
* Run the `release` workflow on the `main` branch, e.g. via `gh workflow run release -f release_type=minor` (`release_type` can be `major`, `minor` or `patch`; you can also override `python_version`)
* Consider running `gh run watch` or `gh run view --web` to watch the progress
**Manual release:**

View File

@ -61,7 +61,7 @@ Why Python?::
point, I wasn't comfortable with C++ so that wasn't an alternative.
But isn't Python too slow for a browser?::
https://www.infoworld.com/d/application-development/van-rossum-python-not-too-slow-188715[It's generally less of a problem than one would expect.]
https://www.infoworld.com/article/2303031/van-rossum-python-is-not-too-slow-2.html[It's generally less of a problem than one would expect.]
Most of the heavy lifting of qutebrowser is done by Qt and
QtWebKit/QtWebEngine in C++, with the
https://wiki.python.org/moin/GlobalInterpreterLock[GIL] released.
@ -141,7 +141,7 @@ The comma prefix is used to make sure user-defined bindings don't conflict with
the built-in ones.
+
Note that you might need an additional package (e.g.
https://www.archlinux.org/packages/community/any/youtube-dl/[youtube-dl] on
https://archlinux.org/packages/extra/any/yt-dlp/[yt-dlp] on
Archlinux) to play web videos with mpv.
+
There is a very useful script for mpv, which emulates "unique application"

View File

@ -179,7 +179,7 @@ customizable for a given <<patterns,URL patterns>>.
[source,python]
----
config.set('content.images', False, '*://example.com/')
config.set('content.images', False, '*://example.com/*')
----
Alternatively, you can use `with config.pattern(...) as p:` to get a shortcut
@ -187,7 +187,7 @@ similar to `c.` which is scoped to the given domain:
[source,python]
----
with config.pattern('*://example.com/') as p:
with config.pattern('*://example.com/*') as p:
p.content.images = False
----
@ -416,6 +416,8 @@ Pre-built colorschemes
- https://github.com/gicrisf/qute-city-lights[City Lights (matte dark)]
- https://github.com/catppuccin/qutebrowser[Catppuccin]
- https://github.com/iruzo/matrix-qutebrowser[Matrix]
- https://github.com/harmtemolder/qutebrowser-solarized[Solarized]
- https://github.com/Rehpotsirhc-z/qutebrowser-doom-one[Doom One]
Avoiding flake8 errors
^^^^^^^^^^^^^^^^^^^^^^
@ -452,7 +454,7 @@ Various emacs/conkeror-like keybinding configs exist:
- https://gitlab.com/Kaligule/qutebrowser-emacs-config/blob/master/config.py[Kaligule]
- https://web.archive.org/web/20210512185023/https://me0w.net/pit/1540882719[nm0i]
- https://www.reddit.com/r/qutebrowser/comments/eh10i7/config_share_qute_with_emacs_keybindings/[jasonsun0310]
- https://git.sr.ht/~willvaughn/dots/tree/mjolnir/item/.config/qutebrowser/qutemacs.py[willvaughn]
- https://git.sr.ht/~willvaughn/dots/tree/main/item/.config/qutebrowser/qutemacs.py[willvaughn]
It's also mostly possible to get rid of modal keybindings by setting
`input.insert_mode.auto_enter` to `false`, and `input.forward_unbound_keys` to

View File

@ -26,7 +26,7 @@ Getting help
You can get help in the IRC channel
link:ircs://irc.libera.chat:6697/#qutebrowser[`#qutebrowser`] on
https://libera.chat/[Libera Chat]
(https://web.libera.chat/#qutebrowser[webchat], https://matrix.to/#qutebrowser:libera.chat[via Matrix]),
(https://web.libera.chat/#qutebrowser[webchat]),
or by writing a message to the
https://listi.jpberlin.de/mailman/listinfo/qutebrowser[mailinglist] at
mailto:qutebrowser@lists.qutebrowser.org[].

View File

@ -302,6 +302,7 @@
|<<qt.force_software_rendering,qt.force_software_rendering>>|Force software rendering for QtWebEngine.
|<<qt.highdpi,qt.highdpi>>|Turn on Qt HighDPI scaling.
|<<qt.workarounds.disable_accelerated_2d_canvas,qt.workarounds.disable_accelerated_2d_canvas>>|Disable accelerated 2d canvas to avoid graphical glitches.
|<<qt.workarounds.disable_accessibility,qt.workarounds.disable_accessibility>>|Disable accessibility to avoid crashes on Qt 6.10.1.
|<<qt.workarounds.disable_hangouts_extension,qt.workarounds.disable_hangouts_extension>>|Disable the Hangouts extension.
|<<qt.workarounds.locale,qt.workarounds.locale>>|Work around locale parsing issues in QtWebEngine 5.15.3.
|<<qt.workarounds.remove_service_workers,qt.workarounds.remove_service_workers>>|Delete the QtWebEngine Service Worker directory on every start.
@ -2275,21 +2276,22 @@ The following placeholders are defined:
* `{upstream_browser_key}`: "Version" for QtWebKit, "Chrome" for
QtWebEngine.
* `{upstream_browser_version}`: The corresponding Safari/Chrome version.
* `{upstream_browser_version_short}`: The corresponding Safari/Chrome
version, but only with its major version.
* `{qutebrowser_version}`: The currently running qutebrowser version.
The default value is equal to the unchanged user agent of
QtWebKit/QtWebEngine.
The default value is equal to the default user agent of
QtWebKit/QtWebEngine, but with the `QtWebEngine/...` part removed for
increased compatibility.
Note that the value read from JavaScript is always the global value. With
QtWebEngine between 5.12 and 5.14 (inclusive), changing the value exposed
to JavaScript requires a restart.
Note that the value read from JavaScript is always the global value.
This setting supports link:configuring{outfilesuffix}#patterns[URL patterns].
Type: <<types,FormatString>>
Default: +pass:[Mozilla/5.0 ({os_info}) AppleWebKit/{webkit_version} (KHTML, like Gecko) {qt_key}/{qt_version} {upstream_browser_key}/{upstream_browser_version} Safari/{webkit_version}]+
Default: +pass:[Mozilla/5.0 ({os_info}) AppleWebKit/{webkit_version} (KHTML, like Gecko) {upstream_browser_key}/{upstream_browser_version_short} Safari/{webkit_version}]+
[[content.hyperlink_auditing]]
=== content.hyperlink_auditing
@ -2345,18 +2347,20 @@ Default: +pass:[false]+
=== content.javascript.clipboard
Allow JavaScript to read from or write to the clipboard.
With QtWebEngine, writing the clipboard as response to a user interaction is always allowed.
On Qt < 6.8, the `ask` setting is equivalent to `none` and permission needs to be granted manually via this setting.
This setting supports link:configuring{outfilesuffix}#patterns[URL patterns].
Type: <<types,String>>
Type: <<types,JSClipboardPermission>>
Valid values:
* +none+: Disable access to clipboard.
* +access+: Allow reading from and writing to the clipboard.
* +access-paste+: Allow accessing the clipboard and pasting clipboard content.
* +ask+: Prompt when requested (grants 'access-paste' permission).
Default: +pass:[none]+
Default: +pass:[ask]+
[[content.javascript.enabled]]
=== content.javascript.enabled
@ -2765,10 +2769,9 @@ Type: <<types,FlagList>>
Valid values:
* +ua-whatsapp+
* +ua-google+
* +ua-slack+
* +ua-googledocs+
* +ua-gnome-gitlab+
* +js-whatsapp-web+
* +js-discord+
* +js-string-replaceall+
@ -3891,7 +3894,7 @@ Chromium has various sandboxing layers, which should be enabled for normal brows
Open `chrome://sandbox` to see the current sandbox status.
Changing this setting is only recommended if you know what you're doing, as it **disables one of Chromium's security layers**. To avoid sandboxing being accidentally disabled persistently, this setting can only be set via `config.py`, not via `:set`.
See the Chromium documentation for more details:
- https://chromium.googlesource.com/chromium/src/\+/HEAD/docs/linux/sandboxing.md[Linux] - https://chromium.googlesource.com/chromium/src/\+/HEAD/docs/design/sandbox.md[Windows] - https://chromium.googlesource.com/chromium/src/\+/HEAD/docs/design/sandbox_faq.md[FAQ (Windows-centric)]
- https://chromium.googlesource.com/chromium/src/\+/HEAD/sandbox/linux/README.md[Linux] - https://chromium.googlesource.com/chromium/src/\+/HEAD/docs/design/sandbox.md[Windows] - https://chromium.googlesource.com/chromium/src/\+/HEAD/sandbox/mac/README.md[Mac] - https://chromium.googlesource.com/chromium/src/\+/HEAD/docs/design/sandbox_faq.md[FAQ (Windows-centric)]
This setting requires a restart.
@ -3989,11 +3992,29 @@ Type: <<types,String>>
Valid values:
* +always+: Disable accelerated 2d canvas
* +auto+: Disable on Qt6 < 6.6.0, enable otherwise
* +auto+: Disable on Qt versions with known issues, enable otherwise
* +never+: Enable accelerated 2d canvas
Default: +pass:[auto]+
[[qt.workarounds.disable_accessibility]]
=== qt.workarounds.disable_accessibility
Disable accessibility to avoid crashes on Qt 6.10.1.
This setting requires a restart.
This setting is only available with the QtWebEngine backend.
Type: <<types,String>>
Valid values:
* +always+: Disable renderer accessibility
* +auto+: Disable on Qt versions with known issues, enable otherwise
* +never+: Enable renderer accessibility
Default: +pass:[auto]+
[[qt.workarounds.disable_hangouts_extension]]
=== qt.workarounds.disable_hangouts_extension
Disable the Hangouts extension.
@ -4844,6 +4865,7 @@ Lists with duplicate flags are invalid. Each item is checked against the valid v
|FuzzyUrl|A URL which gets interpreted as search if needed.
|IgnoreCase|Whether to search case insensitively.
|Int|Base class for an integer setting.
|JSClipboardPermission|Permission for page JS to access the system clipboard.
|Key|A name of a key.
|List|A list of values.

View File

@ -54,7 +54,7 @@ newer qutebrowser running with:
Note you'll need some basic libraries to use the virtualenv-installed PyQt:
----
# apt install --no-install-recommends git ca-certificates python3 python3-venv libgl1 libxkbcommon-x11-0 libegl1-mesa libfontconfig1 libglib2.0-0 libdbus-1-3 libxcb-cursor0 libxcb-icccm4 libxcb-keysyms1 libxcb-shape0 libnss3 libxcomposite1 libxdamage1 libxrender1 libxrandr2 libxtst6 libxi6 libasound2
# apt install --no-install-recommends git ca-certificates python3 python3-venv libgl1 libxkbcommon-x11-0 libegl1 libfontconfig1 libglib2.0-0 libdbus-1-3 libxcb-cursor0 libxcb-icccm4 libxcb-keysyms1 libxcb-shape0 libnss3 libxcomposite1 libxdamage1 libxrender1 libxrandr2 libxtst6 libxi6 libasound2
----
Additional hints
@ -103,12 +103,18 @@ To be able to play videos with proprietary codecs with QtWebEngine, you will
need to install an additional package from the RPM Fusion Free repository.
For more information see https://rpmfusion.org/Configuration.
With Qt 6 (recommended):
-----
# dnf install libavcodec-freeworld
-----
With Qt 5:
-----
# dnf install qt5-qtwebengine-freeworld
-----
It's currently unknown what the Qt 6 equivalent of this is.
On Archlinux
------------
@ -438,7 +444,7 @@ This installs all needed Python dependencies in a `.venv` subfolder
This comes with an up-to-date Qt/PyQt including a pre-compiled QtWebEngine
binary, but has a few caveats:
- Make sure your `python3` is Python 3.8 or newer, otherwise you'll get a "No
- Make sure your `python3` is Python 3.9 or newer, otherwise you'll get a "No
matching distribution found" error and/or qutebrowser will not run.
- It only works on 64-bit x86 systems, with other architectures you'll get the
same error.

View File

@ -432,32 +432,18 @@ Function .onInit
StrCpy $KeepReg 1
; OS version check
${If} ${RunningX64}
; https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-osversioninfoa#remarks
GetWinVer $R0 Major
!if "${QT5}" == "True"
IntCmpU $R0 6 0 _os_check_fail _os_check_pass
GetWinVer $R1 Minor
IntCmpU $R1 2 _os_check_pass _os_check_fail _os_check_pass
!else
IntCmpU $R0 10 0 _os_check_fail _os_check_pass
GetWinVer $R1 Build
${If} $R1 >= 22000 ; Windows 11 21H2
Goto _os_check_pass
${ElseIf} $R1 >= 14393 ; Windows 10 1607
${AndIf} ${IsNativeAMD64} ; Windows 10 has no x86_64 emulation on arm64
Goto _os_check_pass
${EndIf}
!endif
; https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-osversioninfoa#remarks
; https://learn.microsoft.com/en-us/windows/release-health/release-information
; https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information
${If} ${AtLeastWin11}
Goto _os_check_pass
${ElseIf} ${IsNativeAMD64} ; Windows 10 has no x86_64 emulation on arm64
${AndIf} ${AtLeastWin10}
${AndIf} ${AtLeastBuild} 17763 ; Windows 10 1809 (also in error message below)
Goto _os_check_pass
${EndIf}
_os_check_fail:
!if "${QT5}" == "True"
MessageBox MB_OK|MB_ICONSTOP "This version of ${PRODUCT_NAME} requires a 64-bit$\r$\n\
version of Windows 8 or later."
!else
MessageBox MB_OK|MB_ICONSTOP "This version of ${PRODUCT_NAME} requires a 64-bit$\r$\n\
version of Windows 10 1607 or later."
!endif
MessageBox MB_OK|MB_ICONSTOP "This version of ${PRODUCT_NAME} requires a 64-bit$\r$\n\
version of Windows 10 1809 or later."
Abort
_os_check_pass:

View File

@ -131,9 +131,6 @@ ShowUninstDetails hide
!define /ifndef DIST_DIR ".\..\..\dist\${PRODUCT_NAME}-${VERSION}"
!endif
; If not defined, assume Qt6 (requires a more recent windows version)
!define /ifndef QT5 "False"
; Pack the exe header with upx if UPX is defined.
!ifdef UPX
!packhdr "$%TEMP%\exehead.tmp" '"upx" "--ultra-brute" "$%TEMP%\exehead.tmp"'

View File

@ -44,6 +44,14 @@
</content_rating>
<releases>
<!-- Add new releases here -->
<release version='3.6.3' date='2025-11-30'/>
<release version='3.6.2' date='2025-11-27'/>
<release version='3.6.1' date='2025-11-03'/>
<release version='3.6.0' date='2025-10-24'/>
<release version='3.5.1' date='2025-06-05'/>
<release version='3.5.0' date='2025-04-12'/>
<release version="3.4.0" date="2024-12-14"/>
<release version="3.3.1" date="2024-10-12"/>
<release version="3.3.0" date="2024-10-12"/>
<release version="3.2.1" date="2024-06-25"/>
<release version="3.2.0" date="2024-06-03"/>

View File

@ -48,7 +48,7 @@ Categories=Network;WebBrowser;
Exec=qutebrowser --untrusted-args %u
Terminal=false
StartupNotify=true
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/qute;
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/rdf+xml;image/gif;image/webp;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/qute;
Keywords=Browser
Actions=new-window;preferences;

View File

@ -25,24 +25,66 @@ INFO_PLIST_UPDATES = {
"CFBundleURLName": "local file URL",
"CFBundleURLSchemes": ["file"]
}],
'CFBundleDocumentTypes': [{
"CFBundleTypeExtensions": ["html", "htm"],
"CFBundleTypeMIMETypes": ["text/html"],
"CFBundleTypeName": "HTML document",
"CFBundleTypeOSTypes": ["HTML"],
"CFBundleTypeRole": "Viewer",
}, {
"CFBundleTypeExtensions": ["xhtml"],
"CFBundleTypeMIMETypes": ["text/xhtml"],
"CFBundleTypeName": "XHTML document",
"CFBundleTypeRole": "Viewer",
}, {
"CFBundleTypeExtensions": ["mhtml"],
"CFBundleTypeMIMETypes": ["multipart/related", "application/x-mimearchive", "message/rfc822"],
"CFBundleTypeName": "MHTML document",
"CFBundleTypeRole": "Viewer",
}],
'CFBundleDocumentTypes': [
{
"CFBundleTypeIconFile": "document.icns",
"CFBundleTypeName": name,
"CFBundleTypeRole": "Viewer",
"LSItemContentTypes": [content_type],
}
for name, content_type in [
("GIF image", "com.compuserve.gif"),
("HTML document", "public.html"),
("XHTML document", "public.xhtml"),
("JavaScript script", "com.netscape.javascript-source"),
("JPEG image", "public.jpeg"),
("MHTML document", "org.ietf.mhtml"),
("HTML5 Audio (Ogg)", "org.xiph.ogg-audio"),
("HTML5 Video (Ogg)", "org.xiph.oggv"),
("PNG image", "public.png"),
("SVG document", "public.svg-image"),
("Plain text document", "public.text"),
("HTML5 Video (WebM)", "org.webmproject.webm"),
("WebP image", "org.webmproject.webp"),
("PDF Document", "com.adobe.pdf"),
]
],
'UTImportedTypeDeclarations': [
{
"UTTypeConformsTo": ["public.data", "public.content"],
"UTTypeDescription": "MIME HTML document",
"UTTypeIconFile": "document.icns",
"UTTypeIdentifier": "org.ietf.mhtml",
"UTTypeReferenceURL": "https://www.ietf.org/rfc/rfc2557",
"UTTypeTagSpecification": {
"com.apple.ostype": "MHTM",
"public.filename-extension": ["mht", "mhtml"],
"public.mime-type": ["multipart/related", "application/x-mimearchive"],
},
},
{
"UTTypeConformsTo": ["public.audio"],
"UTTypeDescription": "Ogg Audio",
"UTTypeIconFile": "document.icns",
"UTTypeIdentifier": "org.xiph.ogg-audio",
"UTTypeReferenceURL": "https://xiph.org/ogg/",
"UTTypeTagSpecification": {
"public.filename-extension": ["ogg", "oga"],
"public.mime-type": ["audio/ogg"],
},
},
{
"UTTypeConformsTo": ["public.movie"],
"UTTypeDescription": "Ogg Video",
"UTTypeIconFile": "document.icns",
"UTTypeIdentifier": "org.xiph.ogv",
"UTTypeReferenceURL": "https://xiph.org/ogg/",
"UTTypeTagSpecification": {
"public.filename-extension": ["ogm", "ogv"],
"public.mime-type": ["video/ogg"],
},
},
],
# https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_macos
#
# Keys based on Google Chrome's .app, except Bluetooth keys which seem to

View File

@ -1,9 +0,0 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
build==1.2.2
check-manifest==0.49
importlib_metadata==8.5.0
packaging==24.1
pyproject_hooks==1.2.0
tomli==2.0.1
zipp==3.20.2

View File

@ -1 +0,0 @@
check-manifest

View File

@ -1,54 +1,73 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
annotated-types==0.7.0
anyio==4.12.0
autocommand==2.2.2
backports.tarfile==1.2.0
build==1.2.2
bump2version==1.0.1
certifi==2024.8.30
cffi==1.17.1
charset-normalizer==3.3.2
cryptography==43.0.1
docutils==0.20.1
bracex==2.6
build==1.3.0
bump-my-version==1.2.5
certifi==2025.11.12
cffi==2.0.0
charset-normalizer==3.4.4
click==8.1.8
cryptography==46.0.3
docutils==0.22.3
exceptiongroup==1.3.1
github3.py==4.0.1
hunter==3.7.0
idna==3.10
importlib_metadata==8.5.0
importlib_resources==6.4.5
h11==0.16.0
httpcore==1.0.9
httpx==0.28.1
hunter==3.9.0
id==1.5.0
idna==3.11
importlib_metadata==8.7.0
importlib_resources==6.5.2
inflect==7.3.1
jaraco.classes==3.4.0
jaraco.collections==5.1.0
jaraco.context==6.0.1
jaraco.functools==4.1.0
jaraco.functools==4.0.1
jaraco.text==3.12.1
jeepney==0.8.0
keyring==25.4.1
jeepney==0.9.0
keyring==25.7.0
manhole==1.8.1
markdown-it-py==3.0.0
mdurl==0.1.2
more-itertools==10.5.0
nh3==0.2.18
packaging==24.1
pkginfo==1.10.0
platformdirs==4.3.6
pycparser==2.22
Pygments==2.18.0
PyJWT==2.9.0
more-itertools==10.8.0
nh3==0.3.2
packaging==25.0
platformdirs==4.4.0
prompt_toolkit==3.0.52
pycparser==2.23
pydantic==2.12.5
pydantic-settings==2.11.0
pydantic_core==2.41.5
Pygments==2.19.2
PyJWT==2.10.1
Pympler==1.1
pyproject_hooks==1.2.0
PyQt-builder==1.16.4
PyQt-builder==1.19.1
python-dateutil==2.9.0.post0
readme_renderer==43.0
requests==2.32.3
python-dotenv==1.2.1
questionary==2.1.1
readme_renderer==44.0
requests==2.32.5
requests-toolbelt==1.0.0
rfc3986==2.0.0
rich==13.8.1
rich==14.2.0
rich-click==1.9.4
SecretStorage==3.3.3
sip==6.8.6
six==1.16.0
tomli==2.0.1
twine==5.1.1
sip==6.14.0
six==1.17.0
tomli==2.3.0
tomlkit==0.13.3
twine==6.2.0
typeguard==4.3.0
typing_extensions==4.12.2
uritemplate==4.1.1
# urllib3==2.2.3
zipp==3.20.2
typing-inspection==0.4.2
typing_extensions==4.15.0
uritemplate==4.2.0
# urllib3==2.6.2
wcmatch==10.1
wcwidth==0.2.14
zipp==3.23.0

View File

@ -1,7 +1,7 @@
hunter
pympler
github3.py
bump2version
bump-my-version
requests
pyqt-builder
build
@ -9,6 +9,7 @@ twine
# Included to override setuptools' vendored version that is being included in
# the lock file by pip freeze.
importlib_resources
platformdirs
# Already included via test requirements

View File

@ -1,23 +1,23 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
attrs==24.2.0
flake8==7.1.1
flake8-bugbear==24.8.19
flake8-builtins==2.5.0
flake8-comprehensions==3.15.0
attrs==25.4.0
flake8==7.3.0
flake8-bugbear==24.12.12
flake8-builtins==3.0.0
flake8-comprehensions==3.17.0
flake8-debugger==4.1.2
flake8-deprecated==2.2.1
flake8-docstrings==1.7.0
flake8-future-import==0.4.7
flake8-plugin-utils==1.3.3
flake8-pytest-style==2.0.0
flake8-pytest-style==2.1.0
flake8-string-format==0.3.0
flake8-tidy-imports==4.10.0
flake8-tidy-imports==4.12.0
flake8-tuple==0.4.1
mccabe==0.7.0
pep8-naming==0.14.1
pycodestyle==2.12.1
pep8-naming==0.15.1
pycodestyle==2.14.0
pydocstyle==6.3.0
pyflakes==3.2.0
six==1.16.0
snowballstemmer==2.2.0
pyflakes==3.4.0
six==1.17.0
snowballstemmer==3.0.1

View File

@ -1,21 +1,20 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
chardet==5.2.0
diff_cover==9.2.0
importlib_resources==6.4.5
Jinja2==3.1.4
lxml==5.3.0
MarkupSafe==2.1.5
mypy==1.11.2
mypy-extensions==1.0.0
pluggy==1.5.0
Pygments==2.18.0
diff_cover==10.0.0
Jinja2==3.1.6
librt==0.7.3
lxml==6.0.2
MarkupSafe==3.0.3
mypy==1.19.0
mypy_extensions==1.1.0
pathspec==0.12.1
pluggy==1.6.0
Pygments==2.19.2
PyQt5-stubs==5.15.6.0
tomli==2.0.1
types-colorama==0.4.15.20240311
types-docutils==0.21.0.20240907
types-Pygments==2.18.0.20240506
types-PyYAML==6.0.12.20240917
types-setuptools==75.1.0.20240917
typing_extensions==4.12.2
zipp==3.20.2
tomli==2.3.0
types-colorama==0.4.15.20250801
types-docutils==0.22.3.20251115
types-Pygments==2.19.0.20251121
types-PyYAML==6.0.12.20250915
typing_extensions==4.15.0

View File

@ -6,6 +6,3 @@ PyQt5-stubs
types-PyYAML
types-colorama
types-Pygments
# So stubs are available even on newer Python versions
importlib_resources

View File

@ -1,8 +1,8 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
altgraph==0.17.4
importlib_metadata==8.5.0
packaging==24.1
pyinstaller==6.10.0
pyinstaller-hooks-contrib==2024.8
zipp==3.20.2
altgraph==0.17.5
importlib_metadata==8.7.0
packaging==25.0
pyinstaller==6.17.0
pyinstaller-hooks-contrib==2025.10
zipp==3.23.0

View File

@ -1,26 +1,28 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
astroid==3.2.4
certifi==2024.8.30
cffi==1.17.1
charset-normalizer==3.3.2
cryptography==43.0.1
dill==0.3.9
astroid==3.3.11
certifi==2025.11.12
cffi==2.0.0
charset-normalizer==3.4.4
cryptography==46.0.3
dill==0.4.0
github3.py==4.0.1
idna==3.10
isort==5.13.2
idna==3.11
importlib_metadata==8.7.0
isort==6.1.0
mccabe==0.7.0
pefile==2024.8.26
platformdirs==4.3.6
pycparser==2.22
PyJWT==2.9.0
pylint==3.2.7
platformdirs==4.4.0
pycparser==2.23
PyJWT==2.10.1
pylint==3.3.9
python-dateutil==2.9.0.post0
./scripts/dev/pylint_checkers
requests==2.32.3
six==1.16.0
tomli==2.0.1
tomlkit==0.13.2
typing_extensions==4.12.2
uritemplate==4.1.1
# urllib3==2.2.3
requests==2.32.5
six==1.17.0
tomli==2.3.0
tomlkit==0.13.3
typing_extensions==4.15.0
uritemplate==4.2.0
# urllib3==2.6.2
zipp==3.23.0

View File

@ -7,7 +7,6 @@ pefile
# fix qute-pylint location
#@ replace: qute[_-]pylint.* ./scripts/dev/pylint_checkers
#@ markers: typed-ast python_version<"3.8"
# Already included via test requirements
#@ ignore: urllib3

View File

@ -1,5 +1,5 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
PyQt5==5.15.2 # rq.filter: == 5.15.2
PyQt5_sip==12.15.0
PyQt5_sip==12.17.1
PyQtWebEngine==5.15.2 # rq.filter: == 5.15.2

View File

@ -1,7 +1,7 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
PyQt5==5.15.11 # rq.filter: < 5.16
PyQt5-Qt5==5.15.15
PyQt5_sip==12.15.0
PyQt5-Qt5==5.15.18
PyQt5_sip==12.17.1
PyQtWebEngine==5.15.7 # rq.filter: < 5.16
PyQtWebEngine-Qt5==5.15.15
PyQtWebEngine-Qt5==5.15.18

View File

@ -1,7 +1,7 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
PyQt5==5.15.11
PyQt5-Qt5==5.15.15
PyQt5_sip==12.15.0
PyQt5-Qt5==5.15.18
PyQt5_sip==12.17.1
PyQtWebEngine==5.15.7
PyQtWebEngine-Qt5==5.15.15
PyQtWebEngine-Qt5==5.15.18

View File

@ -0,0 +1,8 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
PyQt6==6.10.1
PyQt6-Qt6==6.10.1
PyQt6-WebEngine==6.10.0
PyQt6-WebEngine-Qt6==6.10.1
PyQt6_sip==13.10.2
--extra-index-url https://www.riverbankcomputing.com/pypi/simple/

View File

@ -0,0 +1,8 @@
PyQt6 >= 6.10, < 6.11
PyQt6-Qt6 >= 6.10, < 6.11
PyQt6-WebEngine >= 6.10, < 6.11
PyQt6-WebEngine-Qt6 >= 6.10, < 6.11
# WORKAROUND for https://www.riverbankcomputing.com/pipermail/pyqt/2025-October/046347.html
#@ add: --extra-index-url https://www.riverbankcomputing.com/pypi/simple/
--extra-index-url https://www.riverbankcomputing.com/pypi/simple/

View File

@ -4,4 +4,4 @@ PyQt6==6.2.3
PyQt6-Qt6==6.2.4
PyQt6-WebEngine==6.2.1
PyQt6-WebEngine-Qt6==6.2.4
PyQt6_sip==13.8.0
PyQt6_sip==13.10.2

View File

@ -4,4 +4,4 @@ PyQt6==6.3.1
PyQt6-Qt6==6.3.2
PyQt6-WebEngine==6.3.1
PyQt6-WebEngine-Qt6==6.3.2
PyQt6_sip==13.8.0
PyQt6_sip==13.10.2

View File

@ -4,4 +4,4 @@ PyQt6==6.4.2
PyQt6-Qt6==6.4.3
PyQt6-WebEngine==6.4.0
PyQt6-WebEngine-Qt6==6.4.3
PyQt6_sip==13.8.0
PyQt6_sip==13.10.2

View File

@ -4,4 +4,4 @@ PyQt6==6.5.3
PyQt6-Qt6==6.5.3
PyQt6-WebEngine==6.5.0
PyQt6-WebEngine-Qt6==6.5.3
PyQt6_sip==13.8.0
PyQt6_sip==13.10.2

View File

@ -4,4 +4,4 @@ PyQt6==6.6.1
PyQt6-Qt6==6.6.3
PyQt6-WebEngine==6.6.0
PyQt6-WebEngine-Qt6==6.6.3
PyQt6_sip==13.8.0
PyQt6_sip==13.10.2

View File

@ -5,4 +5,4 @@ PyQt6-Qt6==6.7.3
PyQt6-WebEngine==6.7.0
PyQt6-WebEngine-Qt6==6.7.3
PyQt6-WebEngineSubwheel-Qt6==6.7.3
PyQt6_sip==13.8.0
PyQt6_sip==13.10.2

View File

@ -0,0 +1,7 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
PyQt6==6.8.1
PyQt6-Qt6==6.8.2
PyQt6-WebEngine==6.8.0
PyQt6-WebEngine-Qt6==6.8.2
PyQt6_sip==13.10.2

View File

@ -0,0 +1,4 @@
PyQt6 >= 6.8, < 6.9
PyQt6-Qt6 >= 6.8, < 6.9
PyQt6-WebEngine >= 6.8, < 6.9
PyQt6-WebEngine-Qt6 >= 6.8, < 6.9

View File

@ -0,0 +1,7 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
PyQt6==6.9.1
PyQt6-Qt6==6.9.2
PyQt6-WebEngine==6.9.0
PyQt6-WebEngine-Qt6==6.9.2
PyQt6_sip==13.10.2

View File

@ -0,0 +1,4 @@
PyQt6 >= 6.9, < 6.10
PyQt6-Qt6 >= 6.9, < 6.10
PyQt6-WebEngine >= 6.9, < 6.10
PyQt6-WebEngine-Qt6 >= 6.9, < 6.10

View File

@ -1,8 +1,8 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
PyQt6==6.7.1
PyQt6-Qt6==6.7.3
PyQt6-WebEngine==6.7.0
PyQt6-WebEngine-Qt6==6.7.3
PyQt6-WebEngineSubwheel-Qt6==6.7.3
PyQt6_sip==13.8.0
PyQt6==6.10.1
PyQt6-Qt6==6.10.1
PyQt6-WebEngine==6.10.0
PyQt6-WebEngine-Qt6==6.10.1
PyQt6_sip==13.10.2
--extra-index-url https://www.riverbankcomputing.com/pypi/simple/

View File

@ -2,3 +2,7 @@ PyQt6
PyQt6-Qt6
PyQt6-WebEngine
PyQt6-WebEngine-Qt6
# WORKAROUND for https://www.riverbankcomputing.com/pipermail/pyqt/2025-October/046347.html
#@ add: --extra-index-url https://www.riverbankcomputing.com/pypi/simple/
--extra-index-url https://www.riverbankcomputing.com/pypi/simple/

View File

@ -1,8 +1,8 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
PyQt6==6.7.1
PyQt6-Qt6==6.7.3
PyQt6-WebEngine==6.7.0
PyQt6-WebEngine-Qt6==6.7.3
PyQt6-WebEngineSubwheel-Qt6==6.7.3
PyQt6_sip==13.8.0
PyQt6==6.10.1
PyQt6-Qt6==6.10.1
PyQt6-WebEngine==6.10.0
PyQt6-WebEngine-Qt6==6.10.1
PyQt6_sip==13.10.2
--extra-index-url https://www.riverbankcomputing.com/pypi/simple/

View File

@ -2,3 +2,7 @@ PyQt6
PyQt6-Qt6
PyQt6-WebEngine
PyQt6-WebEngine-Qt6
# WORKAROUND for https://www.riverbankcomputing.com/pipermail/pyqt/2025-October/046347.html
#@ add: --extra-index-url https://www.riverbankcomputing.com/pypi/simple/
--extra-index-url https://www.riverbankcomputing.com/pypi/simple/

View File

@ -1,17 +1,18 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
build==1.2.2
certifi==2024.8.30
charset-normalizer==3.3.2
docutils==0.20.1
idna==3.10
importlib_metadata==8.5.0
packaging==24.1
Pygments==2.18.0
build==1.3.0
certifi==2025.11.12
charset-normalizer==3.4.4
check-manifest==0.51
docutils==0.22.3
idna==3.11
importlib_metadata==8.7.0
packaging==25.0
Pygments==2.19.2
pyproject_hooks==1.2.0
pyroma==4.2
requests==2.32.3
tomli==2.0.1
trove-classifiers==2024.9.12
urllib3==2.2.3
zipp==3.20.2
pyroma==5.0.1
requests==2.32.5
tomli==2.3.0
trove-classifiers==2025.12.1.14
urllib3==2.6.2
zipp==3.23.0

View File

@ -1 +1,2 @@
pyroma
check-manifest

View File

@ -12,12 +12,7 @@ PyYAML
#@ add: pyobjc-core ; sys_platform=="darwin"
#@ add: pyobjc-framework-Cocoa ; sys_platform=="darwin"
## stdlib backports
importlib_resources
## Optional dependencies
Pygments # For :view-source --pygments or on QtWebKit
colorama # Colored log output on Windows
adblock # Improved adblocking
#@ markers: importlib_resources python_version=="3.8.*"

View File

@ -1,26 +1,26 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
alabaster==0.7.13
babel==2.16.0
certifi==2024.8.30
charset-normalizer==3.3.2
docutils==0.20.1
idna==3.10
alabaster==0.7.16
babel==2.17.0
certifi==2025.11.12
charset-normalizer==3.4.4
docutils==0.21.2
idna==3.11
imagesize==1.4.1
importlib_metadata==8.5.0
Jinja2==3.1.4
MarkupSafe==2.1.5
packaging==24.1
Pygments==2.18.0
pytz==2024.2
requests==2.32.3
snowballstemmer==2.2.0
Sphinx==7.1.2
sphinxcontrib-applehelp==1.0.4
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.1
importlib_metadata==8.7.0
Jinja2==3.1.6
MarkupSafe==3.0.3
packaging==25.0
Pygments==2.19.2
requests==2.32.5
snowballstemmer==3.0.1
Sphinx==7.4.7
sphinxcontrib-applehelp==2.0.0
sphinxcontrib-devhelp==2.0.0
sphinxcontrib-htmlhelp==2.1.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
urllib3==2.2.3
zipp==3.20.2
sphinxcontrib-qthelp==2.0.0
sphinxcontrib-serializinghtml==2.0.0
tomli==2.3.0
urllib3==2.6.2
zipp==3.23.0

View File

@ -2,12 +2,13 @@
# bzr+lp:beautifulsoup
beautifulsoup4
git+https://github.com/cherrypy/cheroot.git
git+https://github.com/nedbat/coveragepy.git#egg=coverage[toml]
coverage[toml] @ git+https://github.com/nedbat/coveragepy.git
git+https://github.com/pallets/flask.git
git+https://github.com/pallets/werkzeug.git # transitive dep, but needed to work
git+https://github.com/HypothesisWorks/hypothesis.git#subdirectory=hypothesis-python
git+https://github.com/pytest-dev/pytest.git
git+https://github.com/pytest-dev/pytest-bdd.git
gherkin-official<31.0.0 # https://github.com/cucumber/gherkin/issues/373
git+https://github.com/ionelmc/pytest-benchmark.git
git+https://github.com/pytest-dev/pytest-instafail.git
git+https://github.com/pytest-dev/pytest-mock.git

View File

@ -1,66 +1,67 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
attrs==24.2.0
attrs==25.4.0
autocommand==2.2.2
backports.tarfile==1.2.0
beautifulsoup4==4.12.3
blinker==1.8.2
certifi==2024.8.30
charset-normalizer==3.3.2
cheroot==10.0.1
click==8.1.7
coverage==7.6.1
exceptiongroup==1.2.2
execnet==2.1.1
filelock==3.16.1
Flask==3.0.3
hunter==3.7.0
hypothesis==6.112.2
idna==3.10
importlib_metadata==8.5.0
importlib_resources==6.4.5 ; python_version=="3.8.*"
beautifulsoup4==4.14.3
blinker==1.9.0
certifi==2025.11.12
charset-normalizer==3.4.4
cheroot==11.1.2
click==8.1.8
coverage==7.10.7
exceptiongroup==1.3.1
execnet==2.1.2
filelock==3.19.1
Flask==3.1.2
gherkin-official==29.0.0
hunter==3.9.0
hypothesis==6.141.1
idna==3.11
importlib_metadata==8.7.0
importlib_resources==6.5.2
inflect==7.3.1
iniconfig==2.0.0
iniconfig==2.1.0
itsdangerous==2.2.0
jaraco.collections==5.1.0
jaraco.context==6.0.1
jaraco.functools==4.1.0
jaraco.functools==4.0.1
jaraco.text==3.12.1
# Jinja2==3.1.4
Mako==1.3.5
# Jinja2==3.1.6
Mako==1.3.10
manhole==1.8.1
# MarkupSafe==2.1.5
more-itertools==10.5.0
packaging==24.1
# MarkupSafe==3.0.3
more-itertools==10.8.0
packaging==25.0
parse==1.20.2
parse_type==0.6.3
platformdirs==4.3.6
pillow==10.4.0
pluggy==1.5.0
parse_type==0.6.6
pillow==11.3.0
platformdirs==4.4.0
pluggy==1.6.0
py-cpuinfo==9.0.0
Pygments==2.18.0
pytest==8.3.3
pytest-bdd==7.3.0
pytest-benchmark==4.0.0
pytest-cov==5.0.0
Pygments==2.19.2
pytest==8.4.2
pytest-bdd==8.1.0
pytest-benchmark==5.2.3
pytest-cov==7.0.0
pytest-instafail==0.5.0
pytest-mock==3.14.0
pytest-qt==4.4.0
pytest-repeat==0.9.3
pytest-rerunfailures==14.0
pytest-xdist==3.6.1
pytest-xvfb==3.0.0
pytest-mock==3.15.1
pytest-qt==4.5.0
pytest-repeat==0.9.4
pytest-rerunfailures==16.0.1
pytest-xdist==3.8.0
pytest-xvfb==3.1.1
PyVirtualDisplay==3.0
requests==2.32.3
requests-file==2.1.0
six==1.16.0
requests==2.32.5
requests-file==3.0.1
six==1.17.0
sortedcontainers==2.4.0
soupsieve==2.6
tldextract==5.1.2
tomli==2.0.1
soupsieve==2.8
tldextract==5.3.0
tomli==2.3.0
typeguard==4.3.0
typing_extensions==4.12.2
urllib3==2.2.3
vulture==2.12
Werkzeug==3.0.4
zipp==3.20.2
typing_extensions==4.15.0
urllib3==2.6.2
vulture==2.14
Werkzeug==3.1.4
zipp==3.23.0

View File

@ -39,7 +39,6 @@ tldextract
# Include them here even though we don't need them to make sure we at least
# get an up to date version.
importlib_resources
#@ markers: importlib_resources python_version=="3.8.*"
jaraco.context
platformdirs

View File

@ -1,17 +1,19 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
cachetools==5.5.0
cachetools==6.2.3
chardet==5.2.0
colorama==0.4.6
distlib==0.3.8
filelock==3.16.1
packaging==24.1
pip==24.2
platformdirs==4.3.6
pluggy==1.5.0
pyproject-api==1.8.0
setuptools==75.1.0
tomli==2.0.1
tox==4.20.0
virtualenv==20.26.6
wheel==0.44.0
distlib==0.4.0
filelock==3.19.1
packaging==25.0
pip==25.3
platformdirs==4.4.0
pluggy==1.6.0
pyproject-api==1.9.1
setuptools==80.9.0
tomli==2.3.0
tox==4.30.3 ; python_full_version!="3.14.0b1"
typing_extensions==4.15.0
virtualenv==20.35.4
wheel==0.45.1
tox @ git+https://github.com/tox-dev/tox ; python_full_version=="3.14.0b1"

View File

@ -1,2 +1,5 @@
tox
wheel
#@ markers: tox python_full_version!="3.14.0b1"
#@ add: tox @ git+https://github.com/tox-dev/tox ; python_full_version=="3.14.0b1"

View File

@ -1,4 +1,4 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
tomli==2.0.1
vulture==2.12
tomli==2.3.0
vulture==2.14

View File

@ -1,5 +1,5 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
pathspec==0.12.1
PyYAML==6.0.2
yamllint==1.35.1
PyYAML==6.0.3
yamllint==1.37.1

View File

@ -106,6 +106,8 @@ The following userscripts can be found on their own repositories.
More powerfully manage single window sessions
- [qutebrowser-url-mutator](https://codeberg.org/mister_monster/qutebrowser-url-mutator):
automatically mutates input URLs based on configurable rules
- [qute-translate-popup](https://github.com/JohnBardoe/qute-translate-popup):
selected text translation, with a qute popup!
[Zotero]: https://www.zotero.org/
[Pocket]: https://getpocket.com/

View File

@ -143,7 +143,7 @@ no_entries_found() {
# expected to write the username of that entry to the $username variable and
# the corresponding password to $password
# shellcheck disable=SC2317
# shellcheck disable=SC2329
reset_backend() {
init() { true ; }
query_entries() { true ; }
@ -199,7 +199,8 @@ choose_entry_zenity() {
}
choose_entry_zenity_radio() {
zenity_helper() { # shellcheck disable=SC2317
# shellcheck disable=SC2329
zenity_helper() {
awk '{ print $0 ; print $0 }' \
| zenity --list --radiolist \
--title "qutebrowser password fill" \
@ -279,7 +280,7 @@ pass_backend() {
# =======================================================
# backend: secret
# shellcheck disable=SC2317
# shellcheck disable=SC2329
secret_backend() {
init() {
return

View File

@ -96,7 +96,8 @@ def ask_password(password_prompt_invocation):
raise Exception('Could not unlock vault')
master_pass = process.stdout.strip()
return subprocess.check_output(
['bw', 'unlock', '--raw', master_pass],
['bw', 'unlock', '--raw', '--passwordenv', 'BW_MASTERPASS'],
env={**os.environ, 'BW_MASTERPASS': master_pass},
text=True,
).strip()
@ -132,7 +133,7 @@ def get_session_key(auto_lock, password_prompt_invocation):
def pass_(domain, encoding, auto_lock, password_prompt_invocation):
session_key = get_session_key(auto_lock, password_prompt_invocation)
process = subprocess.run(
['bw', 'list', 'items', '--session', session_key, '--url', domain],
['bw', 'list', 'items', '--nointeraction', '--session', session_key, '--url', domain],
capture_output=True,
)
@ -141,6 +142,10 @@ def pass_(domain, encoding, auto_lock, password_prompt_invocation):
msg = 'Bitwarden CLI returned for {:s} - {:s}'.format(domain, err)
stderr(msg)
if "Vault is locked" in err:
stderr("Bitwarden Vault got locked, trying again with clean session")
return pass_(domain, encoding, 0, password_prompt_invocation)
if process.returncode:
return '[]'
@ -152,7 +157,7 @@ def pass_(domain, encoding, auto_lock, password_prompt_invocation):
def get_totp_code(selection_id, domain_name, encoding, auto_lock, password_prompt_invocation):
session_key = get_session_key(auto_lock, password_prompt_invocation)
process = subprocess.run(
['bw', 'get', 'totp', '--session', session_key, selection_id],
['bw', 'get', 'totp', '--nointeraction', '--session', session_key, selection_id],
capture_output=True,
)
@ -162,6 +167,10 @@ def get_totp_code(selection_id, domain_name, encoding, auto_lock, password_promp
msg = 'Bitwarden CLI returned for {:s} - {:s}'.format(domain_name, err)
stderr(msg)
if "Vault is locked" in err:
stderr("Bitwarden Vault got locked, trying again with clean session")
return get_totp_code(selection_id, domain_name, encoding, 0, password_prompt_invocation)
if process.returncode:
return '[]'
@ -195,12 +204,20 @@ def main(arguments):
# the registered domain name and finally: the IPv4 address if that's what
# the URL represents
candidates = []
for target in filter(None, [
extract_result.fqdn,
extract_result.registered_domain,
extract_result.subdomain + '.' + extract_result.domain,
extract_result.domain,
extract_result.ipv4]):
for target in filter(
None,
[
extract_result.fqdn,
(
extract_result.top_domain_under_public_suffix
if hasattr(extract_result, "top_domain_under_public_suffix")
else extract_result.registered_domain
),
extract_result.subdomain + "." + extract_result.domain,
extract_result.domain,
extract_result.ipv4,
],
):
target_candidates = json.loads(
pass_(
target,

View File

@ -117,7 +117,20 @@ def main(arguments):
# the URL represents
candidates = []
seen_id = set()
for target in filter(None, [extract_result.fqdn, extract_result.registered_domain, extract_result.subdomain + extract_result.domain, extract_result.domain, extract_result.ipv4]):
for target in filter(
None,
[
extract_result.fqdn,
(
extract_result.top_domain_under_public_suffix
if hasattr(extract_result, "top_domain_under_public_suffix")
else extract_result.registered_domain
),
extract_result.subdomain + extract_result.domain,
extract_result.domain,
extract_result.ipv4,
],
):
target_candidates, err = pass_(target, arguments.io_encoding)
if err:
stderr("LastPass CLI returned for {:s} - {:s}".format(target, err))

View File

@ -243,7 +243,20 @@ def main(arguments):
netloc = urlparse(arguments.url).netloc
for target in filter(None, [extract_result.fqdn, extract_result.registered_domain, extract_result.ipv4, private_domain, netloc]):
for target in filter(
None,
[
extract_result.fqdn,
(
extract_result.top_domain_under_public_suffix
if hasattr(extract_result, "top_domain_under_public_suffix")
else extract_result.registered_domain
),
extract_result.ipv4,
private_domain,
netloc,
],
):
attempted_targets.append(target)
target_candidates = find_pass_candidates(target, unfiltered=arguments.unfiltered)
if not target_candidates:

View File

@ -23,7 +23,7 @@ create_menu() {
done < "$QUTE_CONFIG_DIR"/bookmarks/urls
# Finally history
printf -- '%s\n' "$(sqlite3 -separator ' ' "$QUTE_DATA_DIR/history.sqlite" 'select title, url from CompletionHistory')"
printf -- '%s\n' "$(sqlite3 -separator ' ' "$QUTE_DATA_DIR/history.sqlite" 'select title, url from CompletionHistory ORDER BY last_atime DESC')"
}
get_selection() {

View File

@ -9,18 +9,16 @@
# :spawn --userscript ripbang amazon maps
#
import os, re, requests, sys
from urllib.parse import urlparse, parse_qs
import os, requests, sys
for argument in sys.argv[1:]:
bang = '!' + argument
r = requests.get('https://duckduckgo.com/',
r = requests.get('https://html.duckduckgo.com/html/',
allow_redirects=False,
params={'q': bang + ' SEARCHTEXT'},
headers={'user-agent': 'qutebrowser ripbang'})
searchengine = re.search("url=([^']+)", r.text).group(1)
searchengine = urlparse(searchengine).query
searchengine = parse_qs(searchengine)['uddg'][0]
searchengine = r.headers['location']
searchengine = searchengine.replace('SEARCHTEXT', '{}')
if os.getenv('QUTE_FIFO'):

12
pyproject.toml Normal file
View File

@ -0,0 +1,12 @@
[build-system]
requires = ["setuptools>=42"]
build-backend = "setuptools.build_meta"
[tool.check-manifest]
ignore = [
"qutebrowser/git-commit-id",
"qutebrowser/html/doc",
"qutebrowser/html/doc/*",
"qutebrowser/html/doc/img/cheatsheet-*.png",
"*/__pycache__",
]

View File

@ -1,4 +1,5 @@
[pytest]
pythonpath = .
log_level = NOTSET
addopts = --strict-markers --strict-config --instafail --benchmark-columns=Min,Max,Median
testpaths = tests
@ -19,6 +20,7 @@ markers =
not_frozen: Tests which can't be run if sys.frozen is True.
not_flatpak: Tests which can't be run if running with Flatpak.
no_xvfb: Tests which can't be run with Xvfb.
no_offscreen: Tests which can't be run with the offscreen platform plugin.
frozen: Tests which can only be run if sys.frozen is True.
integration: Tests which test a bigger portion of code
end2end: End to end tests which run qutebrowser as subprocess
@ -41,7 +43,8 @@ markers =
qt6_only: Tests which should only run with Qt 6
qt5_xfail: Tests which fail with Qt 5
qt6_xfail: Tests which fail with Qt 6
qt68_beta4_skip: Fails on Qt 6.8 beta 4
qt69_ci_flaky: Tests which are flaky with Qt 6.9+ on CI
qt69_ci_skip: Tests which should be skipped with Qt 6.9+ on CI
qt_log_level_fail = WARNING
qt_log_ignore =
# GitHub Actions
@ -77,13 +80,29 @@ qt_log_ignore =
# model, for example, when no completion function is available for the
# current text pattern.
QItemSelectionModel: Selecting when no model has been set will result in a no-op.
^QSaveFile::commit: File \(.*/test_failing_flush0/foo\) is not open$
^QSaveFile::commit: File \(.*[/\\]test_failing_flush0[/\\]foo\) is not open$
^The following paths were searched for Qt WebEngine dictionaries:.*
# Qt 6.9 with Xvfb
^Backend texture is not a Vulkan texture\.$
^Compositor returned null texture$
# With offscreen platform plugin
^This plugin does not support (raise\(\)|propagateSizeHints\(\)|createPlatformVulkanInstance|grabbing the keyboard)$
^QRhiGles2: Failed to create (temporary )?context$
^QVulkanInstance: Failed to initialize Vulkan$
^Unable to detect GPU vendor\.$
# Qt 5 on CI with WebKit
^qglx_findConfig: Failed to finding matching FBConfig for QSurfaceFormat\(version 2\.0, options QFlags<QSurfaceFormat::FormatOption>\(\), depthBufferSize -1, redBufferSize 1, greenBufferSize 1, blueBufferSize 1, alphaBufferSize -1, stencilBufferSize -1, samples -1, swapBehavior QSurfaceFormat::SingleBuffer, swapInterval 1, colorSpace QSurfaceFormat::DefaultColorSpace, profile QSurfaceFormat::NoProfile\)$
# Qt 6.8+ debug build
# https://github.com/qutebrowser/qutebrowser/issues/8069#issuecomment-2017644465
^QObject::connect: Connecting from COMPAT signal \(QWebEnginePage::featurePermissionRequest(ed|Canceled)\(QUrl,QWebEnginePage::Feature\)\)
xfail_strict = true
filterwarnings =
error
default:Test process .* failed to terminate!:UserWarning
# Python 3.12: https://github.com/ionelmc/pytest-benchmark/issues/240 (fixed but not released)
ignore:(datetime\.)?datetime\.utcnow\(\) is deprecated and scheduled for removal in a future version\. Use timezone-aware objects to represent datetimes in UTC. (datetime\.)?datetime\.now\(datetime\.UTC\)\.:DeprecationWarning:pytest_benchmark\.utils
# https://github.com/cucumber/gherkin/commit/2f4830093149eae7ff7bd82f683b3d3bb7320d39
# https://github.com/pytest-dev/pytest-bdd/issues/752
ignore:'maxsplit' is passed as positional argument:DeprecationWarning:gherkin.gherkin_line
# https://github.com/ionelmc/pytest-benchmark/issues/283
ignore:FileType is deprecated\. Simply open files after parsing arguments\.:PendingDeprecationWarning:pytest_benchmark.plugin
faulthandler_timeout = 90
xvfb_colordepth = 24

View File

@ -11,10 +11,10 @@ _year = datetime.date.today().year
__author__ = "Florian Bruhin"
__copyright__ = "Copyright 2013-{} Florian Bruhin (The Compiler)".format(_year)
__license__ = "GPL"
__license__ = "GPL-3.0-or-later"
__maintainer__ = __author__
__email__ = "mail@qutebrowser.org"
__version__ = "3.3.0"
__version__ = "3.6.3"
__version_info__ = tuple(int(part) for part in __version__.split('.'))
__description__ = "A keyboard-driven, vim-like browser based on Python and Qt."

View File

@ -35,7 +35,8 @@ Possible values:
import inspect
from typing import Any, Callable, Iterable, Protocol, Optional, Dict, cast
from typing import Any, Protocol, Optional, cast
from collections.abc import Iterable, Callable
from qutebrowser.utils import qtutils
from qutebrowser.commands import command, cmdexc
@ -101,7 +102,7 @@ class _CmdHandlerType(Protocol):
Below, we cast the decorated function to _CmdHandlerType to make mypy aware of this.
"""
qute_args: Optional[Dict[str, 'command.ArgInfo']]
qute_args: Optional[dict[str, 'command.ArgInfo']]
def __call__(self, *args: Any, **kwargs: Any) -> Any:
...

View File

@ -7,7 +7,8 @@
"""Hooks for extensions."""
import importlib
from typing import Callable, Any
from typing import Any
from collections.abc import Callable
from qutebrowser.extensions import loader

View File

@ -29,7 +29,8 @@ import tempfile
import pathlib
import datetime
import argparse
from typing import Iterable, Optional, List, Tuple
from typing import Optional
from collections.abc import Iterable
from qutebrowser.qt import machinery
from qutebrowser.qt.widgets import QApplication, QWidget
@ -330,7 +331,7 @@ def _open_special_pages(args):
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window='last-focused')
pages: List[Tuple[str, bool, str]] = [
pages: list[tuple[str, bool, str]] = [
# state, condition, URL
('quickstart-done',
True,

View File

@ -9,8 +9,8 @@ import pathlib
import itertools
import functools
import dataclasses
from typing import (cast, TYPE_CHECKING, Any, Callable, Iterable, List, Optional,
Sequence, Set, Type, Union, Tuple)
from typing import (cast, TYPE_CHECKING, Any, Optional, Union)
from collections.abc import Iterable, Sequence, Callable
from qutebrowser.qt import machinery
from qutebrowser.qt.core import (pyqtSignal, pyqtSlot, QUrl, QObject, QSizeF, Qt,
@ -29,7 +29,7 @@ if TYPE_CHECKING:
from qutebrowser.keyinput import modeman
from qutebrowser.config import config, websettings
from qutebrowser.utils import (utils, objreg, usertypes, log, qtutils,
urlutils, message, jinja, version)
urlutils, message, jinja)
from qutebrowser.misc import miscwidgets, objects, sessions
from qutebrowser.browser import eventfilter, inspector
from qutebrowser.qt import sip
@ -60,7 +60,7 @@ def create(win_id: int,
mode_manager = modeman.instance(win_id)
if objects.backend == usertypes.Backend.QtWebEngine:
from qutebrowser.browser.webengine import webenginetab
tab_class: Type[AbstractTab] = webenginetab.WebEngineTab
tab_class: type[AbstractTab] = webenginetab.WebEngineTab
elif objects.backend == usertypes.Backend.QtWebKit:
from qutebrowser.browser.webkit import webkittab
tab_class = webkittab.WebKitTab
@ -142,7 +142,7 @@ class AbstractAction:
"""Attribute ``action`` of AbstractTab for Qt WebActions."""
action_base: Type[Union['QWebPage.WebAction', 'QWebEnginePage.WebAction']]
action_base: type[Union['QWebPage.WebAction', 'QWebEnginePage.WebAction']]
def __init__(self, tab: 'AbstractTab') -> None:
self._widget = cast(_WidgetType, None)
@ -639,7 +639,7 @@ class AbstractScroller(QObject):
def pos_px(self) -> QPoint:
raise NotImplementedError
def pos_perc(self) -> Tuple[int, int]:
def pos_perc(self) -> tuple[int, int]:
raise NotImplementedError
def to_perc(self, x: float = None, y: float = None) -> None:
@ -765,10 +765,10 @@ class AbstractHistory:
def _go_to_item(self, item: Any) -> None:
raise NotImplementedError
def back_items(self) -> List[Any]:
def back_items(self) -> list[Any]:
raise NotImplementedError
def forward_items(self) -> List[Any]:
def forward_items(self) -> list[Any]:
raise NotImplementedError
@ -1018,7 +1018,7 @@ class AbstractTab(QWidget):
# Note that we remember hosts here, without scheme/port:
# QtWebEngine/Chromium also only remembers hostnames, and certificates are
# for a given hostname anyways.
_insecure_hosts: Set[str] = set()
_insecure_hosts: set[str] = set()
# Sub-APIs initialized by subclasses
history: AbstractHistory
@ -1177,37 +1177,6 @@ class AbstractTab(QWidget):
navigation.url.errorString()))
navigation.accepted = False
# WORKAROUND for QtWebEngine >= 6.2 not allowing form requests from
# qute:// to outside domains.
needs_load_workarounds = (
objects.backend == usertypes.Backend.QtWebEngine and
version.qtwebengine_versions().webengine >= utils.VersionNumber(6, 2)
)
if (
needs_load_workarounds and
self.url() == QUrl("qute://start/") and
navigation.navigation_type == navigation.Type.form_submitted and
navigation.url.matches(
QUrl(config.val.url.searchengines['DEFAULT']),
urlutils.FormatOption.REMOVE_QUERY)
):
log.webview.debug(
"Working around qute://start loading issue for "
f"{navigation.url.toDisplayString()}")
navigation.accepted = False
self.load_url(navigation.url)
if (
needs_load_workarounds and
self.url() == QUrl("qute://bookmarks/") and
navigation.navigation_type == navigation.Type.back_forward
):
log.webview.debug(
"Working around qute://bookmarks loading issue for "
f"{navigation.url.toDisplayString()}")
navigation.accepted = False
self.load_url(navigation.url)
@pyqtSlot(bool)
def _on_load_finished(self, ok: bool) -> None:
assert self._widget is not None

View File

@ -2,12 +2,15 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
# pylint: disable=too-many-positional-arguments
"""Command dispatcher for TabbedBrowser."""
import os.path
import shlex
import functools
from typing import cast, Callable, Dict, Union, Optional
from typing import cast, Union, Optional
from collections.abc import Callable
from qutebrowser.qt.widgets import QApplication, QTabBar
from qutebrowser.qt.core import Qt, QUrl, QEvent, QUrlQuery
@ -68,7 +71,10 @@ class CommandDispatcher:
def _current_index(self):
"""Convenience method to get the current widget index."""
return self._tabbed_browser.widget.currentIndex()
current_index = self._tabbed_browser.widget.currentIndex()
if current_index == -1:
raise cmdutils.CommandError("No WebView available yet!")
return current_index
def _current_url(self):
"""Convenience method to get the current url."""
@ -636,7 +642,7 @@ class CommandDispatcher:
widget = self._current_widget()
url = self._current_url()
handlers: Dict[str, Callable[..., QUrl]] = {
handlers: dict[str, Callable[..., QUrl]] = {
'prev': functools.partial(navigate.prevnext, prev=True),
'next': functools.partial(navigate.prevnext, prev=False),
'up': navigate.path_up,
@ -862,10 +868,6 @@ class CommandDispatcher:
Args:
count: How many tabs to switch back.
"""
if self._count() == 0:
# Running :tab-prev after last tab was closed
# See https://github.com/qutebrowser/qutebrowser/issues/1448
return
newidx = self._current_index() - count
if newidx >= 0:
self._set_current_index(newidx)
@ -882,10 +884,6 @@ class CommandDispatcher:
Args:
count: How many tabs to switch forward.
"""
if self._count() == 0:
# Running :tab-next after last tab was closed
# See https://github.com/qutebrowser/qutebrowser/issues/1448
return
newidx = self._current_index() + count
if newidx < self._count():
self._set_current_index(newidx)
@ -1136,8 +1134,7 @@ class CommandDispatcher:
else:
cmd = os.path.expanduser(cmd)
proc = guiprocess.GUIProcess(what='command', verbose=verbose,
output_messages=output_messages,
parent=self._tabbed_browser)
output_messages=output_messages)
if detach:
ok = proc.start_detached(cmd, args)
if not ok:
@ -1166,7 +1163,7 @@ class CommandDispatcher:
if count is not None:
env['QUTE_COUNT'] = str(count)
idx = self._current_index()
idx = self._tabbed_browser.widget.currentIndex()
if idx != -1:
env['QUTE_TAB_INDEX'] = str(idx + 1)
env['QUTE_TITLE'] = self._tabbed_browser.widget.page_title(idx)

View File

@ -13,7 +13,8 @@ import functools
import pathlib
import tempfile
import enum
from typing import Any, Dict, IO, List, MutableSequence, Optional, Union
from typing import Any, IO, Optional, Union
from collections.abc import MutableSequence
from qutebrowser.qt.core import (pyqtSlot, pyqtSignal, Qt, QObject, QModelIndex,
QTimer, QAbstractListModel, QUrl)
@ -187,15 +188,22 @@ def transform_path(path):
"""
if not utils.is_windows:
return path
path = utils.expand_windows_drive(path)
# Drive dependent working directories are not supported, e.g.
# E:filename is invalid
if re.search(r'^[A-Z]:[^\\]', path, re.IGNORECASE):
return None
# Paths like COM1, ...
# See https://github.com/qutebrowser/qutebrowser/issues/82
if pathlib.Path(path).is_reserved():
return None
if sys.version_info[:2] >= (3, 13):
if os.path.isreserved(path): # pylint: disable=no-member
return None
else:
if pathlib.Path(path).is_reserved(): # pylint: disable=else-if-used
return None
return path
@ -447,7 +455,7 @@ class AbstractDownloadItem(QObject):
UnsupportedAttribute, IO[bytes], None
] = UnsupportedAttribute()
self.raw_headers: Union[
UnsupportedAttribute, Dict[bytes, bytes]
UnsupportedAttribute, dict[bytes, bytes]
] = UnsupportedAttribute()
self._filename: Optional[str] = None
@ -899,7 +907,7 @@ class AbstractDownloadManager(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self.downloads: List[AbstractDownloadItem] = []
self.downloads: list[AbstractDownloadItem] = []
self._update_timer = usertypes.Timer(self, 'download-update')
self._update_timer.timeout.connect(self._update_gui)
self._update_timer.setInterval(_REFRESH_INTERVAL)

View File

@ -5,7 +5,8 @@
"""The ListView to display downloads in."""
import functools
from typing import Callable, MutableSequence, Tuple, Union
from typing import Union
from collections.abc import MutableSequence, Callable
from qutebrowser.qt.core import pyqtSlot, QSize, Qt
from qutebrowser.qt.widgets import QListView, QSizePolicy, QMenu, QStyleFactory
@ -17,8 +18,8 @@ from qutebrowser.utils import qtutils, utils
_ActionListType = MutableSequence[
Union[
Tuple[None, None], # separator
Tuple[str, Callable[[], None]],
tuple[None, None], # separator
tuple[str, Callable[[], None]],
]
]

View File

@ -6,11 +6,12 @@
from qutebrowser.qt import machinery
from qutebrowser.qt.core import QObject, QEvent, Qt, QTimer
from qutebrowser.qt.gui import QKeyEvent
from qutebrowser.qt.widgets import QWidget
from qutebrowser.config import config
from qutebrowser.utils import log, message, usertypes, qtutils
from qutebrowser.keyinput import modeman
from qutebrowser.utils import log, message, usertypes, qtutils, version, utils
from qutebrowser.keyinput import modeman, keyutils
class ChildEventFilter(QObject):
@ -37,8 +38,8 @@ class ChildEventFilter(QObject):
if event.type() == QEvent.Type.ChildAdded:
child = event.child()
if not isinstance(child, QWidget):
# Can e.g. happen when dragging text
log.misc.debug(f"Ignoring new child {qtutils.qobj_repr(child)}")
# Can e.g. happen when dragging text, or accessibility tree
# nodes since Qt 6.9
return False
log.misc.debug(
@ -54,21 +55,30 @@ class ChildEventFilter(QObject):
# - This is a child event filter on a tab (self._widget is not None)
# - We find an old existing child which is a QQuickWidget and is
# currently focused.
# - We're using QtWebEngine >= 6.4 (older versions are not affected)
# - We're using an affected QtWebEngine version
children = [
c for c in self._widget.findChildren(
QWidget, "", Qt.FindChildOption.FindDirectChildrenOnly)
if c is not child and
c.hasFocus() and
c.metaObject() is not None and
c.metaObject().className() == "QQuickWidget"
c.metaObject().className() == "QQuickWidget" # Qt 6.4+
]
if children:
if children and version.qtwebengine_versions().webengine < utils.VersionNumber(6, 6, 3):
log.misc.debug("Focusing new child")
child.setFocus()
child.installEventFilter(self._filter)
elif event.type() == QEvent.Type.ChildRemoved:
if isinstance(event, QKeyEvent):
# WORKAROUND for unknown (Py)Qt bug
info = keyutils.KeyInfo.from_event(event)
log.misc.warning(
f"ChildEventFilter: ignoring key event {info} "
f"on {qtutils.qobj_repr(obj)}"
)
return False
child = event.child()
log.misc.debug(
f"{qtutils.qobj_repr(obj)}: removed child {qtutils.qobj_repr(child)}")

View File

@ -12,7 +12,8 @@ import functools
import glob
import textwrap
import dataclasses
from typing import cast, List, Sequence, Tuple, Optional
from typing import cast, Optional
from collections.abc import Sequence
from qutebrowser.qt.core import pyqtSignal, QObject, QUrl
@ -207,9 +208,9 @@ class MatchingScripts:
"""All userscripts registered to run on a particular url."""
url: QUrl
start: List[GreasemonkeyScript] = dataclasses.field(default_factory=list)
end: List[GreasemonkeyScript] = dataclasses.field(default_factory=list)
idle: List[GreasemonkeyScript] = dataclasses.field(default_factory=list)
start: list[GreasemonkeyScript] = dataclasses.field(default_factory=list)
end: list[GreasemonkeyScript] = dataclasses.field(default_factory=list)
idle: list[GreasemonkeyScript] = dataclasses.field(default_factory=list)
@dataclasses.dataclass
@ -217,8 +218,8 @@ class LoadResults:
"""The results of loading all Greasemonkey scripts."""
successful: List[GreasemonkeyScript] = dataclasses.field(default_factory=list)
errors: List[Tuple[str, str]] = dataclasses.field(default_factory=list)
successful: list[GreasemonkeyScript] = dataclasses.field(default_factory=list)
errors: list[tuple[str, str]] = dataclasses.field(default_factory=list)
def successful_str(self) -> str:
"""Get a string with all successfully loaded scripts.
@ -294,10 +295,10 @@ class GreasemonkeyManager(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self._run_start: List[GreasemonkeyScript] = []
self._run_end: List[GreasemonkeyScript] = []
self._run_idle: List[GreasemonkeyScript] = []
self._in_progress_dls: List[downloads.AbstractDownloadItem] = []
self._run_start: list[GreasemonkeyScript] = []
self._run_end: list[GreasemonkeyScript] = []
self._run_idle: list[GreasemonkeyScript] = []
self._in_progress_dls: list[downloads.AbstractDownloadItem] = []
def load_scripts(self, *, force: bool = False) -> LoadResults:
"""Re-read Greasemonkey scripts from disk.

View File

@ -12,8 +12,15 @@ import html
import enum
import dataclasses
from string import ascii_lowercase
from typing import (TYPE_CHECKING, Callable, Dict, Iterable, Iterator, List, Mapping,
MutableSequence, Optional, Sequence, Set)
from typing import (TYPE_CHECKING, Optional)
from collections.abc import (
Iterable,
Iterator,
Mapping,
MutableSequence,
Sequence,
Callable,
)
from qutebrowser.qt.core import pyqtSignal, pyqtSlot, QObject, Qt, QUrl
from qutebrowser.qt.widgets import QLabel
@ -175,11 +182,11 @@ class HintContext:
add_history: bool
first: bool
baseurl: QUrl
args: List[str]
args: list[str]
group: str
all_labels: List[HintLabel] = dataclasses.field(default_factory=list)
labels: Dict[str, HintLabel] = dataclasses.field(default_factory=dict)
all_labels: list[HintLabel] = dataclasses.field(default_factory=list)
labels: dict[str, HintLabel] = dataclasses.field(default_factory=dict)
to_follow: Optional[str] = None
first_run: bool = True
filterstr: Optional[str] = None
@ -1033,7 +1040,7 @@ class WordHinter:
def __init__(self) -> None:
# will be initialized on first use.
self.words: Set[str] = set()
self.words: set[str] = set()
self.dictionary = None
def ensure_initialized(self) -> None:
@ -1143,7 +1150,7 @@ class WordHinter:
"""
self.ensure_initialized()
hints = []
used_hints: Set[str] = set()
used_hints: set[str] = set()
words = iter(self.words)
for elem in elems:
hint = self.new_hint_for(elem, used_hints, words)

View File

@ -8,7 +8,8 @@ import os
import time
import contextlib
import pathlib
from typing import cast, Mapping, MutableSequence, Optional
from typing import cast, Optional
from collections.abc import Mapping, MutableSequence
from qutebrowser.qt import machinery
from qutebrowser.qt.core import pyqtSlot, QUrl, QObject, pyqtSignal

View File

@ -6,7 +6,7 @@
import re
import posixpath
from typing import Optional, Set
from typing import Optional
from qutebrowser.qt.core import QUrl
@ -79,7 +79,7 @@ def incdec(url, count, inc_or_dec):
inc_or_dec: Either 'increment' or 'decrement'.
"""
urlutils.ensure_valid(url)
segments: Optional[Set[str]] = (
segments: Optional[set[str]] = (
set(config.val.url.incdec_segments)
)

View File

@ -242,7 +242,7 @@ class PACFetcher(QObject):
pac_prefix = "pac+"
assert url.scheme().startswith(pac_prefix)
url.setScheme(url.scheme()[len(pac_prefix):])
url.setScheme(url.scheme().removeprefix(pac_prefix))
self._pac_url = url
with qtlog.disable_qt_msghandler():

View File

@ -4,7 +4,7 @@
"""Handling of proxies."""
from typing import Optional, List
from typing import Optional
from qutebrowser.qt.core import QUrl, pyqtSlot
from qutebrowser.qt.network import QNetworkProxy, QNetworkProxyFactory, QNetworkProxyQuery
@ -71,7 +71,7 @@ class ProxyFactory(QNetworkProxyFactory):
capabilities &= ~lookup_cap
proxy.setCapabilities(capabilities)
def queryProxy(self, query: QNetworkProxyQuery = QNetworkProxyQuery()) -> List[QNetworkProxy]:
def queryProxy(self, query: QNetworkProxyQuery = QNetworkProxyQuery()) -> list[QNetworkProxy]:
"""Get the QNetworkProxies for a query.
Args:

View File

@ -11,6 +11,7 @@ from qutebrowser.qt.core import QUrl, QUrlQuery
from qutebrowser.utils import resources, javascript, jinja, standarddir, log, urlutils
from qutebrowser.config import config
from qutebrowser.misc import objects
_SYSTEM_PATHS = [
@ -69,19 +70,8 @@ def generate_pdfjs_page(filename, url):
return html
def _generate_polyfills():
return """
if (typeof Promise.withResolvers === 'undefined') {
Promise.withResolvers = function () {
let resolve, reject
const promise = new Promise((res, rej) => {
resolve = res
reject = rej
})
return { promise, resolve, reject }
}
}
"""
def _get_polyfills() -> str:
return resources.read_file("javascript/pdfjs_polyfills.js")
def _generate_pdfjs_script(filename):
@ -121,7 +111,7 @@ def _generate_pdfjs_script(filename):
});
}
});
""").render(url=js_url, polyfills=_generate_polyfills())
""").render(url=js_url, polyfills=_get_polyfills())
def get_pdfjs_res_and_path(path):
@ -138,7 +128,12 @@ def get_pdfjs_res_and_path(path):
content = None
file_path = None
system_paths = _SYSTEM_PATHS + [
if 'no-system-pdfjs' in objects.debug_flags:
system_paths = []
else:
system_paths = _SYSTEM_PATHS[:]
system_paths += [
# fallback
os.path.join(standarddir.data(), 'pdfjs'),
# hardcoded fallback for --temp-basedir
@ -168,7 +163,7 @@ def get_pdfjs_res_and_path(path):
if path == "build/pdf.worker.mjs":
content = b"\n".join(
[
_generate_polyfills().encode("ascii"),
_get_polyfills().encode("ascii"),
content,
]
)

View File

@ -9,7 +9,7 @@ import os.path
import shutil
import functools
import dataclasses
from typing import Dict, IO, Optional
from typing import IO, Optional
from qutebrowser.qt.core import pyqtSlot, pyqtSignal, QTimer, QUrl
from qutebrowser.qt.widgets import QApplication
@ -73,7 +73,7 @@ class DownloadItem(downloads.AbstractDownloadItem):
"""
super().__init__(manager=manager, parent=manager)
self.fileobj: Optional[IO[bytes]] = None
self.raw_headers: Dict[bytes, bytes] = {}
self.raw_headers: dict[bytes, bytes] = {}
self._autoclose = True
self._retry_info = None

View File

@ -18,7 +18,8 @@ import textwrap
import urllib
import collections
import secrets
from typing import TypeVar, Callable, Dict, List, Optional, Union, Sequence, Tuple
from typing import TypeVar, Optional, Union
from collections.abc import Sequence, Callable
from qutebrowser.qt.core import QUrlQuery, QUrl
@ -35,7 +36,7 @@ pyeval_output = ":pyeval was never called"
csrf_token: Optional[str] = None
_HANDLERS: Dict[str, "_HandlerCallable"] = {}
_HANDLERS: dict[str, "_HandlerCallable"] = {}
class Error(Exception):
@ -77,7 +78,7 @@ class Redirect(Exception):
# Return value: (mimetype, data) (encoded as utf-8 if a str is returned)
_HandlerRet = Tuple[str, Union[str, bytes]]
_HandlerRet = tuple[str, Union[str, bytes]]
_HandlerCallable = Callable[[QUrl], _HandlerRet]
_Handler = TypeVar('_Handler', bound=_HandlerCallable)
@ -105,7 +106,7 @@ class add_handler: # noqa: N801,N806 pylint: disable=invalid-name
return self._function(url)
def data_for_url(url: QUrl) -> Tuple[str, bytes]:
def data_for_url(url: QUrl) -> tuple[str, bytes]:
"""Get the data to show for the given URL.
Args:
@ -122,25 +123,24 @@ def data_for_url(url: QUrl) -> Tuple[str, bytes]:
path = url.path()
host = url.host()
query = url.query()
# A url like "qute:foo" is split as "scheme:path", not "scheme:host".
log.misc.debug("url: {}, path: {}, host {}".format(
url.toDisplayString(), path, host))
if not path or not host:
new_url = QUrl()
new_url.setScheme('qute')
# When path is absent, e.g. qute://help (with no trailing slash)
if host:
new_url.setHost(host)
# When host is absent, e.g. qute:help
else:
new_url.setHost(path)
if not host:
# Redirect qute:help -> qute://help/
new_url = QUrl(url)
new_url.setHost(path)
new_url.setPath('/')
if query:
new_url.setQuery(query)
if new_url.host(): # path was a valid host
raise Redirect(new_url)
if not new_url.host(): # Valid path but not valid host
raise UrlInvalidError(f"Invalid host (from path): {path!r}")
raise Redirect(new_url)
if not path:
# Redirect qute://help -> qute://help/
new_url = QUrl(url)
new_url.setPath('/')
raise Redirect(new_url)
try:
handler = _HANDLERS[host]
@ -180,7 +180,7 @@ def qute_bookmarks(_url: QUrl) -> _HandlerRet:
@add_handler('tabs')
def qute_tabs(_url: QUrl) -> _HandlerRet:
"""Handler for qute://tabs. Display information about all open tabs."""
tabs: Dict[str, List[Tuple[str, str]]] = collections.defaultdict(list)
tabs: dict[str, list[tuple[str, str]]] = collections.defaultdict(list)
for win_id, window in objreg.window_registry.items():
if sip.isdeleted(window):
continue
@ -201,7 +201,7 @@ def qute_tabs(_url: QUrl) -> _HandlerRet:
def history_data(
start_time: float,
offset: int = None
) -> Sequence[Dict[str, Union[str, int]]]:
) -> Sequence[dict[str, Union[str, int]]]:
"""Return history data.
Arguments:

View File

@ -10,11 +10,12 @@ import html
import enum
import netrc
import tempfile
from typing import Callable, Mapping, List, Optional, Iterable, Iterator
from typing import Optional
from collections.abc import Mapping, Iterable, Iterator, Callable
from qutebrowser.qt.core import QUrl, pyqtBoundSignal
from qutebrowser.config import config
from qutebrowser.config import config, configtypes
from qutebrowser.utils import (usertypes, message, log, objreg, jinja, utils,
qtutils, version, urlutils)
from qutebrowser.mainwindow import mainwindow
@ -25,8 +26,15 @@ class CallSuper(Exception):
"""Raised when the caller should call the superclass instead."""
def custom_headers(url):
"""Get the combined custom headers."""
def custom_headers(
url: QUrl, *, fallback_accept_language: bool = True
) -> list[tuple[bytes, bytes]]:
"""Get the combined custom headers.
Arguments:
fallback_accept_language: Whether to include the global (rather than
per-domain override) accept language header as well.
"""
headers = {}
dnt_config = config.instance.get('content.headers.do_not_track', url=url)
@ -40,9 +48,17 @@ def custom_headers(url):
encoded_value = b"" if value is None else value.encode('ascii')
headers[encoded_header] = encoded_value
# On QtWebEngine, we have fallback_accept_language set to False here for XHR
# requests, so that we don't end up overriding headers that are set via the XHR API.
#
# The global Accept-Language header is set via
# QWebEngineProfile::setHttpAcceptLanguage already anyways, so we only need
# to take care of URL pattern overrides here.
#
# note: Once we drop QtWebKit, we could hardcode fallback_accept_language to False.
accept_language = config.instance.get('content.headers.accept_language',
url=url)
if accept_language is not None:
url=url, fallback=fallback_accept_language)
if accept_language is not None and not isinstance(accept_language, usertypes.Unset):
headers[b'Accept-Language'] = accept_language.encode('ascii')
return sorted(headers.items())
@ -303,6 +319,7 @@ def feature_permission(url, option, msg, yes_action, no_action, abort_on,
None otherwise.
"""
config_val = config.instance.get(option, url=url)
opt = config.instance.get_opt(option)
if config_val == 'ask':
if url.isValid():
urlstr = url.toString(QUrl.UrlFormattingOption.RemovePassword | QUrl.ComponentFormattingOption.FullyEncoded)
@ -328,12 +345,21 @@ def feature_permission(url, option, msg, yes_action, no_action, abort_on,
cancel_action=no_action, abort_on=abort_on,
title='Permission request', text=text, url=urlstr,
option=option)
elif config_val:
if isinstance(opt.typ, configtypes.AsBool):
config_val = opt.typ.to_bool(config_val)
if config_val is True:
yes_action()
return None
else:
elif config_val is False:
no_action()
return None
else:
raise AssertionError(
f"Unsupported value for permission prompt setting ({option}), expected boolean or "
f"'ask', got: {config_val} ({type(config_val)})"
)
def get_tab(win_id, target):
@ -445,7 +471,7 @@ class FileSelectionMode(enum.Enum):
folder = enum.auto()
def choose_file(qb_mode: FileSelectionMode) -> List[str]:
def choose_file(qb_mode: FileSelectionMode) -> list[str]:
"""Select file(s)/folder for up-/downloading, using an external command.
Args:
@ -485,10 +511,10 @@ def choose_file(qb_mode: FileSelectionMode) -> List[str]:
def _execute_fileselect_command(
command: List[str],
command: list[str],
qb_mode: FileSelectionMode,
tmpfilename: Optional[str] = None
) -> List[str]:
) -> list[str]:
"""Execute external command to choose file.
Args:
@ -522,7 +548,7 @@ def _execute_fileselect_command(
def _validated_selected_files(
qb_mode: FileSelectionMode,
selected_files: List[str],
selected_files: list[str],
) -> Iterator[str]:
"""Validates selected files if they are.

View File

@ -15,7 +15,7 @@ import os.path
import html
import functools
import collections
from typing import MutableMapping
from collections.abc import MutableMapping
from qutebrowser.qt.core import pyqtSignal, QUrl, QObject

View File

@ -4,7 +4,8 @@
"""Generic web element related code."""
from typing import Iterator, Optional, Set, TYPE_CHECKING, Union, Dict
from typing import Optional, TYPE_CHECKING, Union
from collections.abc import Iterator
import collections.abc
from qutebrowser.qt import machinery
@ -93,7 +94,7 @@ class AbstractWebElement(collections.abc.MutableMapping): # type: ignore[type-a
"""Get the geometry for this element."""
raise NotImplementedError
def classes(self) -> Set[str]:
def classes(self) -> set[str]:
"""Get a set of classes assigned to this element."""
raise NotImplementedError
@ -336,7 +337,7 @@ class AbstractWebElement(collections.abc.MutableMapping): # type: ignore[type-a
log.webelem.debug("Sending fake click to {!r} at position {} with "
"target {}".format(self, pos, click_target))
target_modifiers: Dict[usertypes.ClickTarget, KeyboardModifierType] = {
target_modifiers: dict[usertypes.ClickTarget, KeyboardModifierType] = {
usertypes.ClickTarget.normal: Qt.KeyboardModifier.NoModifier,
usertypes.ClickTarget.window: Qt.KeyboardModifier.AltModifier | Qt.KeyboardModifier.ShiftModifier,
usertypes.ClickTarget.tab: Qt.KeyboardModifier.ControlModifier,

View File

@ -125,8 +125,8 @@ import copy
import enum
import dataclasses
import collections
from typing import (Any, Iterator, Mapping, MutableMapping, Optional, Set, Tuple, Union,
Sequence, List)
from typing import (Any, Optional, Union)
from collections.abc import Iterator, Mapping, MutableMapping, Sequence
from qutebrowser.config import config
from qutebrowser.utils import usertypes, utils, log, version
@ -212,7 +212,7 @@ class _Setting:
return str(value)
return str(self.mapping[value])
def chromium_tuple(self, value: Any) -> Optional[Tuple[str, str]]:
def chromium_tuple(self, value: Any) -> Optional[tuple[str, str]]:
"""Get the Chromium key and value, or None if no value should be set."""
if self.mapping is not None and self.mapping[value] is None:
return None
@ -242,7 +242,7 @@ class _Definition:
def __init__(
self,
*args: _Setting,
mandatory: Set[str],
mandatory: set[str],
prefix: str,
switch_names: Mapping[Optional[str], str] = None,
) -> None:
@ -255,7 +255,7 @@ class _Definition:
else:
self._switch_names = {None: _BLINK_SETTINGS}
def prefixed_settings(self) -> Iterator[Tuple[str, _Setting]]:
def prefixed_settings(self) -> Iterator[tuple[str, _Setting]]:
"""Get all "prepared" settings.
Yields tuples which contain the Chromium setting key (e.g. 'blink-settings' or
@ -399,7 +399,7 @@ def settings(
*,
versions: version.WebEngineVersions,
special_flags: Sequence[str],
) -> Mapping[str, Sequence[Tuple[str, str]]]:
) -> Mapping[str, Sequence[tuple[str, str]]]:
"""Get necessary blink settings to configure dark mode for QtWebEngine.
Args:
@ -413,12 +413,12 @@ def settings(
variant = _variant(versions)
log.init.debug(f"Darkmode variant: {variant.name}")
result: Mapping[str, List[Tuple[str, str]]] = collections.defaultdict(list)
result: Mapping[str, list[tuple[str, str]]] = collections.defaultdict(list)
blink_settings_flag = f'--{_BLINK_SETTINGS}='
for flag in special_flags:
if flag.startswith(blink_settings_flag):
for pair in flag[len(blink_settings_flag):].split(','):
for pair in flag.removeprefix(blink_settings_flag).split(','):
key, val = pair.split('=', maxsplit=1)
result[_BLINK_SETTINGS].append((key, val))

View File

@ -109,6 +109,7 @@ class RequestInterceptor(QWebEngineUrlRequestInterceptor):
}
new_types = {
"WebSocket": interceptors.ResourceType.websocket, # added in Qt 6.4
"Json": interceptors.ResourceType.json, # added in Qt 6.8
}
for qt_name, qb_value in new_types.items():
qt_value = getattr(
@ -187,7 +188,9 @@ class RequestInterceptor(QWebEngineUrlRequestInterceptor):
if request.is_blocked:
info.block(True)
for header, value in shared.custom_headers(url=url):
for header, value in shared.custom_headers(
url=url, fallback_accept_language=not is_xhr
):
if header.lower() == b'accept' and is_xhr:
# https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader
# says: "If no Accept header has been set using this, an Accept header

View File

@ -33,7 +33,8 @@ import dataclasses
import itertools
import functools
import subprocess
from typing import Any, List, Dict, Optional, Iterator, Type, TYPE_CHECKING
from typing import Any, Optional, TYPE_CHECKING
from collections.abc import Iterator
from qutebrowser.qt import machinery
from qutebrowser.qt.core import (Qt, QObject, QVariant, QMetaType, QByteArray, pyqtSlot,
@ -195,7 +196,7 @@ class NotificationBridgePresenter(QObject):
def __init__(self, parent: QObject = None) -> None:
super().__init__(parent)
self._active_notifications: Dict[int, 'QWebEngineNotification'] = {}
self._active_notifications: dict[int, 'QWebEngineNotification'] = {}
self._adapter: Optional[AbstractNotificationAdapter] = None
config.instance.changed.connect(self._init_adapter)
@ -232,8 +233,8 @@ class NotificationBridgePresenter(QObject):
def _get_adapter_candidates(
self,
setting: str,
) -> List[Type[AbstractNotificationAdapter]]:
candidates: Dict[str, List[Type[AbstractNotificationAdapter]]] = {
) -> list[type[AbstractNotificationAdapter]]:
candidates: dict[str, list[type[AbstractNotificationAdapter]]] = {
"libnotify": [
DBusNotificationAdapter,
SystrayNotificationAdapter,
@ -285,7 +286,10 @@ class NotificationBridgePresenter(QObject):
if replaces_id is None:
if notification_id in self._active_notifications:
raise Error(f"Got duplicate id {notification_id}")
message.error(f"Got duplicate notification id {notification_id} "
f"from {self._adapter.NAME}")
self._drop_adapter()
return
qt_notification.show()
self._active_notifications[notification_id] = qt_notification
@ -665,7 +669,7 @@ class _ServerCapabilities:
kde_origin_name: bool
@classmethod
def from_list(cls, capabilities: List[str]) -> "_ServerCapabilities":
def from_list(cls, capabilities: list[str]) -> "_ServerCapabilities":
return cls(
actions='actions' in capabilities,
body_markup='body-markup' in capabilities,
@ -951,10 +955,10 @@ class DBusNotificationAdapter(AbstractNotificationAdapter):
qtutils.extract_enum_val(QMetaType.Type.QStringList),
)
def _get_hints_arg(self, *, origin_url: QUrl, icon: QImage) -> Dict[str, Any]:
def _get_hints_arg(self, *, origin_url: QUrl, icon: QImage) -> dict[str, Any]:
"""Get the hints argument for present()."""
origin_url_str = origin_url.toDisplayString()
hints: Dict[str, Any] = {
hints: dict[str, Any] = {
# Include the origin in case the user wants to do different things
# with different origin's notifications.
"x-qutebrowser-origin": origin_url_str,
@ -984,7 +988,7 @@ class DBusNotificationAdapter(AbstractNotificationAdapter):
title: str,
body: str,
actions: QDBusArgument,
hints: Dict[str, Any],
hints: dict[str, Any],
timeout: int,
) -> Any:
"""Wrapper around DBus call to use keyword args."""

View File

@ -5,7 +5,8 @@
"""QtWebEngine specific part of the web element API."""
from typing import (
TYPE_CHECKING, Any, Callable, Dict, Iterator, Optional, Set, Tuple, Union)
TYPE_CHECKING, Any, Optional, Union)
from collections.abc import Iterator, Callable
from qutebrowser.qt.core import QRect, QEventLoop
from qutebrowser.qt.widgets import QApplication
@ -24,11 +25,11 @@ class WebEngineElement(webelem.AbstractWebElement):
_tab: "webenginetab.WebEngineTab"
def __init__(self, js_dict: Dict[str, Any],
def __init__(self, js_dict: dict[str, Any],
tab: 'webenginetab.WebEngineTab') -> None:
super().__init__(tab)
# Do some sanity checks on the data we get from JS
js_dict_types: Dict[str, Union[type, Tuple[type, ...]]] = {
js_dict_types: dict[str, Union[type, tuple[type, ...]]] = {
'id': int,
'text': str,
'value': (str, int, float),
@ -105,7 +106,7 @@ class WebEngineElement(webelem.AbstractWebElement):
log.stub()
return QRect()
def classes(self) -> Set[str]:
def classes(self) -> set[str]:
"""Get a list of classes assigned to this element."""
return set(self._js_dict['class_name'].split())

View File

@ -12,7 +12,7 @@ Module attributes:
import os
import operator
import pathlib
from typing import cast, Any, List, Optional, Tuple, Union, TYPE_CHECKING
from typing import cast, Any, Optional, Union, TYPE_CHECKING
from qutebrowser.qt import machinery
from qutebrowser.qt.gui import QFont
@ -26,7 +26,7 @@ from qutebrowser.config import config, websettings
from qutebrowser.config.websettings import AttributeInfo as Attr
from qutebrowser.misc import pakjoy
from qutebrowser.utils import (standarddir, qtutils, message, log,
urlmatch, usertypes, objreg, version)
urlmatch, usertypes, objreg, version, utils)
if TYPE_CHECKING:
from qutebrowser.browser.webengine import interceptor
@ -216,6 +216,10 @@ class WebEngineSettings(websettings.AbstractSettings):
QWebEngineSettings.WebAttribute.JavascriptCanAccessClipboard: True,
QWebEngineSettings.WebAttribute.JavascriptCanPaste: True,
},
'ask': {
QWebEngineSettings.WebAttribute.JavascriptCanAccessClipboard: False,
QWebEngineSettings.WebAttribute.JavascriptCanPaste: False,
},
}
def set_unknown_url_scheme_policy(
@ -281,6 +285,7 @@ class ProfileSetter:
self._set_hardcoded_settings()
self.set_persistent_cookie_policy()
self.set_dictionary_language()
self.disable_persistent_permissions_policy()
def _set_hardcoded_settings(self):
"""Set up settings with a fixed value."""
@ -343,7 +348,23 @@ class ProfileSetter:
log.config.debug("Found dicts: {}".format(filenames))
self._profile.setSpellCheckLanguages(filenames)
self._profile.setSpellCheckEnabled(bool(filenames))
should_enable = bool(filenames)
if self._profile.isSpellCheckEnabled() != should_enable:
# Only setting conditionally as a WORKAROUND for a bogus Qt error message:
# https://bugreports.qt.io/browse/QTBUG-131969
self._profile.setSpellCheckEnabled(should_enable)
def disable_persistent_permissions_policy(self):
"""Disable webengine's permission persistence."""
if machinery.IS_QT6: # for mypy
try:
# New in WebEngine 6.8.0
self._profile.setPersistentPermissionsPolicy(
QWebEngineProfile.PersistentPermissionsPolicy.AskEveryTime
)
except AttributeError:
pass
def _update_settings(option):
@ -357,6 +378,12 @@ def _update_settings(option):
def _init_user_agent_str(ua):
global parsed_user_agent
parsed_user_agent = websettings.UserAgent.parse(ua)
if parsed_user_agent.upstream_browser_version.endswith(".0.0.0"):
# https://codereview.qt-project.org/c/qt/qtwebengine/+/616314
# but we still want the full version available to users if they want it.
qtwe_versions = version.qtwebengine_versions()
assert qtwe_versions.chromium is not None
parsed_user_agent.upstream_browser_version = qtwe_versions.chromium
def init_user_agent():
@ -390,16 +417,70 @@ def _init_profile(profile: QWebEngineProfile) -> None:
lambda url: profile.clearVisitedLinks([url]))
_global_settings.init_settings()
_maybe_disable_hangouts_extension(profile)
def _maybe_disable_hangouts_extension(profile: QWebEngineProfile) -> None:
"""Disable the Hangouts extension for Qt 6.10+."""
if not config.val.qt.workarounds.disable_hangouts_extension:
return
if machinery.IS_QT6: # mypy
try:
ext_manager = profile.extensionManager()
except AttributeError:
return # added in QtWebEngine 6.10
qtwe_versions = version.qtwebengine_versions(avoid_init=True)
if (
qtwe_versions.webengine == utils.VersionNumber(6, 10, 1)
and profile.isOffTheRecord()
):
# WORKAROUND for https://github.com/qutebrowser/qutebrowser/issues/8785
log.misc.warning(
"Not disabling Hangouts extension on private profile to avoid "
"QtWebEngine crash with Qt 6.10.1")
return
assert ext_manager is not None # mypy
for info in ext_manager.extensions():
if info.id() == pakjoy.HANGOUTS_EXT_ID:
log.misc.debug(f"Disabling extension: {info.name()}")
# setExtensionEnabled(info, False) seems to segfault
ext_manager.unloadExtension(info)
def _clear_webengine_permissions_json():
"""Remove QtWebEngine's persistent permissions file, if present.
We have our own permissions feature and don't integrate with their one.
This only needs to be called when you are on Qt6.8 but PyQt<6.8, since if
we have access to the `setPersistentPermissionsPolicy()` we will use that
to disable the Qt feature.
This needs to be called before we call `setPersistentStoragePath()`
because Qt will load the file during that.
"""
permissions_file = pathlib.Path(standarddir.data()) / "webengine" / "permissions.json"
try:
permissions_file.unlink(missing_ok=True)
except OSError as err:
log.init.warning(
f"Error while cleaning up webengine permissions file: {err}"
)
def default_qt_profile() -> QWebEngineProfile:
"""Get the default profile from Qt."""
if machinery.IS_QT6:
return QWebEngineProfile("Default")
else:
return QWebEngineProfile.defaultProfile()
def _init_default_profile():
"""Init the default QWebEngineProfile."""
global default_profile
if machinery.IS_QT6:
default_profile = QWebEngineProfile("Default")
else:
default_profile = QWebEngineProfile.defaultProfile()
default_profile = default_qt_profile()
assert not default_profile.isOffTheRecord()
assert parsed_user_agent is None # avoid earlier profile initialization
@ -407,13 +488,25 @@ def _init_default_profile():
init_user_agent()
ua_version = version.qtwebengine_versions()
logger = log.init.warning
if machinery.IS_QT5:
# With Qt 5.15, we can't quite be sure about which QtWebEngine patch version
# we're getting, as ELF parsing might be broken and there's no other way.
# For most of the code, we don't really care about the patch version though.
assert (
non_ua_version.webengine.strip_patch() == ua_version.webengine.strip_patch()
), (non_ua_version, ua_version)
logger = log.init.debug
if ua_version.webengine != non_ua_version.webengine:
log.init.warning(
logger(
"QtWebEngine version mismatch - unexpected behavior might occur, "
"please open a bug about this.\n"
f" Early version: {non_ua_version}\n"
f" Real version: {ua_version}")
_clear_webengine_permissions_json()
default_profile.setCachePath(
os.path.join(standarddir.cache(), 'webengine'))
default_profile.setPersistentStoragePath(
@ -446,13 +539,23 @@ def _init_site_specific_quirks():
# default_ua = ("Mozilla/5.0 ({os_info}) "
# "AppleWebKit/{webkit_version} (KHTML, like Gecko) "
# "{qt_key}/{qt_version} "
# "{upstream_browser_key}/{upstream_browser_version} "
# "{upstream_browser_key}/{upstream_browser_version_short} "
# "Safari/{webkit_version}")
no_qtwe_ua = ("Mozilla/5.0 ({os_info}) "
"AppleWebKit/{webkit_version} (KHTML, like Gecko) "
"{upstream_browser_key}/{upstream_browser_version} "
"Safari/{webkit_version}")
firefox_ua = "Mozilla/5.0 ({os_info}; rv:90.0) Gecko/20100101 Firefox/90.0"
firefox_ua = "Mozilla/5.0 ({os_info}; rv:145.0) Gecko/20100101 Firefox/145.0"
# Needed for gitlab.gnome.org which blocks old Chromium versions outright,
# except when QtWebEngine/... is in the UA.
#
# We could further modify the UA to just "qutebrowser" or something so we don't get
# Anubis at all, but it looks like their Anubis triggers to more than just
# Mozilla/5.0 (also AppleWebKit/... and Chromium/... possibly?), so at that point
# I'm not sure if we can strip down the UA so much without breaking
# something in GitLab as well.
not_mozilla_ua = (
"Mozilla/5.0 ({os_info}) AppleWebKit/{webkit_version} (KHTML, like Gecko) "
"{qt_key}/{qt_version} {upstream_browser_key}/{upstream_browser_version_short} "
"Safari/{webkit_version}"
)
def maybe_newer_chrome_ua(at_least_version):
"""Return a new UA if our current chrome version isn't at least at_least_version."""
@ -467,23 +570,14 @@ def _init_site_specific_quirks():
"Safari/537.36"
)
user_agents = [
# Needed to avoid a ""WhatsApp works with Google Chrome 36+" error
# page which doesn't allow to use WhatsApp Web at all. Also see the
# additional JS quirk: qutebrowser/javascript/quirks/whatsapp_web.user.js
# https://github.com/qutebrowser/qutebrowser/issues/4445
("ua-whatsapp", 'https://web.whatsapp.com/', no_qtwe_ua),
utils.unused(maybe_newer_chrome_ua)
user_agents = [
# Needed to avoid a "you're using a browser [...] that doesn't allow us
# to keep your account secure" error.
# https://github.com/qutebrowser/qutebrowser/issues/5182
("ua-google", 'https://accounts.google.com/*', firefox_ua),
# Needed because Slack adds an error which prevents using it relatively
# aggressively, despite things actually working fine.
# October 2023: Slack claims they only support 112+. On #7951 at least
# one user claims it still works fine on 108 based Qt versions.
("ua-slack", 'https://*.slack.com/*', maybe_newer_chrome_ua(112)),
("ua-google", "https://accounts.google.com/*", firefox_ua),
("ua-gnome-gitlab", "https://gitlab.gnome.org/*", not_mozilla_ua),
]
for name, pattern, ua in user_agents:
@ -509,7 +603,7 @@ def _init_default_settings():
- Make sure the devtools always get images/JS permissions.
- On Qt 6, make sure files in the data path can load external resources.
"""
devtools_settings: List[Tuple[str, Any]] = [
devtools_settings: list[tuple[str, Any]] = [
('content.javascript.enabled', True),
('content.images', True),
('content.cookies.accept', 'all'),
@ -522,7 +616,7 @@ def _init_default_settings():
hide_userconfig=True)
if machinery.IS_QT6:
userscripts_settings: List[Tuple[str, Any]] = [
userscripts_settings: list[tuple[str, Any]] = [
("content.local_content_can_access_remote_urls", True),
("content.local_content_can_access_file_urls", False),
]

Some files were not shown because too many files have changed in this diff Show More