Merge remote-tracking branch 'upstream/main' into tree-tabs-integration
This commit is contained in:
commit
e6524f7959
|
|
@ -1,5 +1,5 @@
|
|||
[tool.bumpversion]
|
||||
current_version = "3.4.0"
|
||||
current_version = "3.5.0"
|
||||
commit = true
|
||||
message = "Release v{new_version}"
|
||||
tag = true
|
||||
|
|
|
|||
|
|
@ -193,6 +193,14 @@ jobs:
|
|||
- testenv: py313-pyqt68
|
||||
os: ubuntu-24.04
|
||||
python: "3.13"
|
||||
### PyQt 6.8 (Python 3.14)
|
||||
- testenv: py314-pyqt68
|
||||
os: ubuntu-24.04
|
||||
python: "3.14-dev"
|
||||
### PyQt 6.9 (Python 3.13)
|
||||
- testenv: py313-pyqt69
|
||||
os: ubuntu-24.04
|
||||
python: "3.13"
|
||||
### macOS Ventura
|
||||
- testenv: py313-pyqt68
|
||||
os: macos-13
|
||||
|
|
@ -228,7 +236,7 @@ jobs:
|
|||
- name: Install apt dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
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
|
||||
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: |
|
||||
|
|
|
|||
|
|
@ -15,16 +15,55 @@ 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.4.1]]
|
||||
v3.4.1 (unreleased)
|
||||
[[v3.5.1]]
|
||||
v3.5.1 (unreleased)
|
||||
-------------------
|
||||
|
||||
Fixed
|
||||
~~~~~
|
||||
|
||||
- Resolved issues in userscripts:
|
||||
* `qute-bitwarden`, `-lastpass` and `-pass` 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
|
||||
~~~~~
|
||||
|
|
@ -34,8 +73,18 @@ Fixed
|
|||
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).
|
||||
- The default user agent now only contains the shortened Chromium version
|
||||
number, which fixes overzealous blocking on ScienceDirect.
|
||||
- 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)
|
||||
|
|
|
|||
|
|
@ -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[].
|
||||
|
|
|
|||
|
|
@ -2296,19 +2296,18 @@ The following placeholders are defined:
|
|||
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_short} 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
|
||||
|
|
@ -2786,9 +2785,7 @@ Type: <<types,FlagList>>
|
|||
|
||||
Valid values:
|
||||
|
||||
* +ua-whatsapp+
|
||||
* +ua-google+
|
||||
* +ua-slack+
|
||||
* +ua-googledocs+
|
||||
* +js-whatsapp-web+
|
||||
* +js-discord+
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
</content_rating>
|
||||
<releases>
|
||||
<!-- Add new releases here -->
|
||||
<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"/>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
# This file is automatically generated by scripts/dev/recompile_requirements.py
|
||||
|
||||
annotated-types==0.7.0
|
||||
anyio==4.8.0
|
||||
anyio==4.9.0
|
||||
autocommand==2.2.2
|
||||
backports.tarfile==1.2.0
|
||||
bracex==2.5.post1
|
||||
build==1.2.2.post1
|
||||
bump-my-version==1.0.2
|
||||
bump-my-version==1.1.2
|
||||
certifi==2025.1.31
|
||||
cffi==1.17.1
|
||||
charset-normalizer==3.4.1
|
||||
|
|
@ -16,7 +16,7 @@ docutils==0.21.2
|
|||
exceptiongroup==1.2.2
|
||||
github3.py==4.0.1
|
||||
h11==0.14.0
|
||||
httpcore==1.0.7
|
||||
httpcore==1.0.8
|
||||
httpx==0.28.1
|
||||
hunter==3.7.0
|
||||
id==1.5.0
|
||||
|
|
@ -37,25 +37,25 @@ mdurl==0.1.2
|
|||
more-itertools==10.6.0
|
||||
nh3==0.2.21
|
||||
packaging==24.2
|
||||
platformdirs==4.3.6
|
||||
platformdirs==4.3.7
|
||||
prompt_toolkit==3.0.50
|
||||
pycparser==2.22
|
||||
pydantic==2.10.6
|
||||
pydantic==2.11.3
|
||||
pydantic-settings==2.8.1
|
||||
pydantic_core==2.27.2
|
||||
pydantic_core==2.33.1
|
||||
Pygments==2.19.1
|
||||
PyJWT==2.10.1
|
||||
Pympler==1.1
|
||||
pyproject_hooks==1.2.0
|
||||
PyQt-builder==1.18.1
|
||||
python-dateutil==2.9.0.post0
|
||||
python-dotenv==1.0.1
|
||||
python-dotenv==1.1.0
|
||||
questionary==2.1.0
|
||||
readme_renderer==44.0
|
||||
requests==2.32.3
|
||||
requests-toolbelt==1.0.0
|
||||
rfc3986==2.0.0
|
||||
rich==13.9.4
|
||||
rich==14.0.0
|
||||
rich-click==1.8.8
|
||||
SecretStorage==3.3.3
|
||||
sip==6.10.0
|
||||
|
|
@ -65,9 +65,10 @@ tomli==2.2.1
|
|||
tomlkit==0.13.2
|
||||
twine==6.1.0
|
||||
typeguard==4.3.0
|
||||
typing_extensions==4.12.2
|
||||
typing-inspection==0.4.0
|
||||
typing_extensions==4.13.2
|
||||
uritemplate==4.1.1
|
||||
# urllib3==2.3.0
|
||||
# urllib3==2.4.0
|
||||
wcmatch==10.0
|
||||
wcwidth==0.2.13
|
||||
zipp==3.21.0
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# This file is automatically generated by scripts/dev/recompile_requirements.py
|
||||
|
||||
attrs==25.1.0
|
||||
flake8==7.1.2
|
||||
attrs==25.3.0
|
||||
flake8==7.2.0
|
||||
flake8-bugbear==24.12.12
|
||||
flake8-builtins==2.5.0
|
||||
flake8-comprehensions==3.16.0
|
||||
|
|
@ -16,8 +16,8 @@ flake8-tidy-imports==4.11.0
|
|||
flake8-tuple==0.4.1
|
||||
mccabe==0.7.0
|
||||
pep8-naming==0.14.1
|
||||
pycodestyle==2.12.1
|
||||
pycodestyle==2.13.0
|
||||
pydocstyle==6.3.0
|
||||
pyflakes==3.2.0
|
||||
pyflakes==3.3.2
|
||||
six==1.17.0
|
||||
snowballstemmer==2.2.0
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
chardet==5.2.0
|
||||
diff_cover==9.2.4
|
||||
Jinja2==3.1.6
|
||||
lxml==5.3.1
|
||||
lxml==5.3.2
|
||||
MarkupSafe==3.0.2
|
||||
mypy==1.15.0
|
||||
mypy-extensions==1.0.0
|
||||
|
|
@ -14,5 +14,5 @@ tomli==2.2.1
|
|||
types-colorama==0.4.15.20240311
|
||||
types-docutils==0.21.0.20241128
|
||||
types-Pygments==2.19.0.20250305
|
||||
types-PyYAML==6.0.12.20241230
|
||||
typing_extensions==4.12.2
|
||||
types-PyYAML==6.0.12.20250402
|
||||
typing_extensions==4.13.2
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ altgraph==0.17.4
|
|||
importlib_metadata==8.6.1
|
||||
packaging==24.2
|
||||
pyinstaller==6.12.0
|
||||
pyinstaller-hooks-contrib==2025.1
|
||||
pyinstaller-hooks-contrib==2025.2
|
||||
zipp==3.21.0
|
||||
|
|
|
|||
|
|
@ -11,16 +11,16 @@ idna==3.10
|
|||
isort==6.0.1
|
||||
mccabe==0.7.0
|
||||
pefile==2024.8.26
|
||||
platformdirs==4.3.6
|
||||
platformdirs==4.3.7
|
||||
pycparser==2.22
|
||||
PyJWT==2.10.1
|
||||
pylint==3.3.5
|
||||
pylint==3.3.6
|
||||
python-dateutil==2.9.0.post0
|
||||
./scripts/dev/pylint_checkers
|
||||
requests==2.32.3
|
||||
six==1.17.0
|
||||
tomli==2.2.1
|
||||
tomlkit==0.13.2
|
||||
typing_extensions==4.12.2
|
||||
typing_extensions==4.13.2
|
||||
uritemplate==4.1.1
|
||||
# urllib3==2.3.0
|
||||
# urllib3==2.4.0
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
# This file is automatically generated by scripts/dev/recompile_requirements.py
|
||||
|
||||
PyQt6==6.9.0
|
||||
PyQt6-Qt6==6.9.0
|
||||
PyQt6-WebEngine==6.9.0
|
||||
PyQt6-WebEngine-Qt6==6.9.0
|
||||
PyQt6_sip==13.10.0
|
||||
|
|
@ -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
|
||||
|
|
@ -1,7 +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==6.9.0
|
||||
PyQt6-Qt6==6.9.0
|
||||
PyQt6-WebEngine==6.9.0
|
||||
PyQt6-WebEngine-Qt6==6.9.0
|
||||
PyQt6_sip==13.10.0
|
||||
|
|
|
|||
|
|
@ -1,7 +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==6.9.0
|
||||
PyQt6-Qt6==6.9.0
|
||||
PyQt6-WebEngine==6.9.0
|
||||
PyQt6-WebEngine-Qt6==6.9.0
|
||||
PyQt6_sip==13.10.0
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@ pyproject_hooks==1.2.0
|
|||
pyroma==4.2
|
||||
requests==2.32.3
|
||||
tomli==2.2.1
|
||||
trove-classifiers==2025.3.3.18
|
||||
urllib3==2.3.0
|
||||
trove-classifiers==2025.4.11.15
|
||||
urllib3==2.4.0
|
||||
zipp==3.21.0
|
||||
|
|
|
|||
|
|
@ -22,5 +22,5 @@ sphinxcontrib-jsmath==1.0.1
|
|||
sphinxcontrib-qthelp==2.0.0
|
||||
sphinxcontrib-serializinghtml==2.0.0
|
||||
tomli==2.2.1
|
||||
urllib3==2.3.0
|
||||
urllib3==2.4.0
|
||||
zipp==3.21.0
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# This file is automatically generated by scripts/dev/recompile_requirements.py
|
||||
|
||||
attrs==25.1.0
|
||||
attrs==25.3.0
|
||||
autocommand==2.2.2
|
||||
backports.tarfile==1.2.0
|
||||
beautifulsoup4==4.13.3
|
||||
|
|
@ -9,45 +9,45 @@ certifi==2025.1.31
|
|||
charset-normalizer==3.4.1
|
||||
cheroot==10.0.1
|
||||
click==8.1.8
|
||||
coverage==7.6.12
|
||||
coverage==7.8.0
|
||||
exceptiongroup==1.2.2
|
||||
execnet==2.1.1
|
||||
filelock==3.17.0
|
||||
filelock==3.18.0
|
||||
Flask==3.1.0
|
||||
gherkin-official==29.0.0
|
||||
hunter==3.7.0
|
||||
hypothesis==6.128.1
|
||||
hypothesis==6.131.0
|
||||
idna==3.10
|
||||
importlib_metadata==8.6.1
|
||||
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.text==3.12.1
|
||||
# Jinja2==3.1.6
|
||||
Mako==1.3.9
|
||||
Mako==1.3.10
|
||||
manhole==1.8.1
|
||||
# MarkupSafe==3.0.2
|
||||
more-itertools==10.6.0
|
||||
packaging==24.2
|
||||
parse==1.20.2
|
||||
parse_type==0.6.4
|
||||
pillow==11.1.0
|
||||
platformdirs==4.3.6
|
||||
pillow==11.2.1
|
||||
platformdirs==4.3.7
|
||||
pluggy==1.5.0
|
||||
py-cpuinfo==9.0.0
|
||||
Pygments==2.19.1
|
||||
pytest==8.3.5
|
||||
pytest-bdd==8.1.0
|
||||
pytest-benchmark==5.1.0
|
||||
pytest-cov==6.0.0
|
||||
pytest-cov==6.1.1
|
||||
pytest-instafail==0.5.0
|
||||
pytest-mock==3.14.0
|
||||
pytest-qt==4.4.0
|
||||
pytest-repeat==0.9.3
|
||||
pytest-repeat==0.9.4
|
||||
pytest-rerunfailures==15.0
|
||||
pytest-xdist==3.6.1
|
||||
pytest-xvfb==3.1.1
|
||||
|
|
@ -57,11 +57,11 @@ requests-file==2.1.0
|
|||
six==1.17.0
|
||||
sortedcontainers==2.4.0
|
||||
soupsieve==2.6
|
||||
tldextract==5.1.3
|
||||
tldextract==5.2.0
|
||||
tomli==2.2.1
|
||||
typeguard==4.3.0
|
||||
typing_extensions==4.12.2
|
||||
urllib3==2.3.0
|
||||
typing_extensions==4.13.2
|
||||
urllib3==2.4.0
|
||||
vulture==2.14
|
||||
Werkzeug==3.1.3
|
||||
zipp==3.21.0
|
||||
|
|
|
|||
|
|
@ -4,15 +4,15 @@ cachetools==5.5.2
|
|||
chardet==5.2.0
|
||||
colorama==0.4.6
|
||||
distlib==0.3.9
|
||||
filelock==3.17.0
|
||||
filelock==3.18.0
|
||||
packaging==24.2
|
||||
pip==25.0.1
|
||||
platformdirs==4.3.6
|
||||
platformdirs==4.3.7
|
||||
pluggy==1.5.0
|
||||
pyproject-api==1.9.0
|
||||
setuptools==76.0.0
|
||||
setuptools==78.1.0
|
||||
tomli==2.2.1
|
||||
tox==4.24.2
|
||||
typing_extensions==4.12.2
|
||||
virtualenv==20.29.3
|
||||
tox==4.25.0
|
||||
typing_extensions==4.13.2
|
||||
virtualenv==20.30.0
|
||||
wheel==0.45.1
|
||||
|
|
|
|||
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
pathspec==0.12.1
|
||||
PyYAML==6.0.2
|
||||
yamllint==1.35.1
|
||||
yamllint==1.37.0
|
||||
|
|
|
|||
|
|
@ -133,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,
|
||||
)
|
||||
|
||||
|
|
@ -142,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 '[]'
|
||||
|
||||
|
|
@ -153,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,
|
||||
)
|
||||
|
||||
|
|
@ -163,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 '[]'
|
||||
|
||||
|
|
@ -196,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,
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ markers =
|
|||
qt5_xfail: Tests which fail with Qt 5
|
||||
qt6_xfail: Tests which fail with Qt 6
|
||||
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
|
||||
|
|
@ -95,5 +96,9 @@ filterwarnings =
|
|||
# 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/pytest-dev/pytest-mock/issues/468
|
||||
ignore:'asyncio\.iscoroutinefunction' is deprecated and slated for removal:DeprecationWarning:pytest_mock.plugin
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -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.4.0"
|
||||
__version__ = "3.5.0"
|
||||
__version_info__ = tuple(int(part) for part in __version__.split('.'))
|
||||
__description__ = "A keyboard-driven, vim-like browser based on Python and Qt."
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,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."""
|
||||
|
|
@ -1315,7 +1318,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)
|
||||
|
|
|
|||
|
|
@ -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 = [
|
||||
|
|
@ -127,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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -495,10 +495,6 @@ def _init_site_specific_quirks():
|
|||
# "{qt_key}/{qt_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_short} "
|
||||
"Safari/{webkit_version}")
|
||||
firefox_ua = "Mozilla/5.0 ({os_info}; rv:136.0) Gecko/20100101 Firefox/136.0"
|
||||
|
||||
def maybe_newer_chrome_ua(at_least_version):
|
||||
|
|
@ -514,23 +510,13 @@ 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),
|
||||
]
|
||||
|
||||
for name, pattern, ua in user_agents:
|
||||
|
|
|
|||
|
|
@ -1363,6 +1363,11 @@ class WebEngineTab(browsertab.AbstractTab):
|
|||
self._widget.page().toHtml(callback)
|
||||
|
||||
def run_js_async(self, code, callback=None, *, world=None):
|
||||
if sip.isdeleted(self._widget):
|
||||
# https://github.com/qutebrowser/qutebrowser/issues/3895
|
||||
log.misc.debug("run_js_async called on deleted tab")
|
||||
return
|
||||
|
||||
world_id_type = Union[QWebEngineScript.ScriptWorldId, int]
|
||||
if world is None:
|
||||
world_id: world_id_type = QWebEngineScript.ScriptWorldId.ApplicationWorld
|
||||
|
|
|
|||
|
|
@ -656,9 +656,7 @@ content.site_specific_quirks.skip:
|
|||
type:
|
||||
name: FlagList
|
||||
valid_values:
|
||||
- ua-whatsapp
|
||||
- ua-google
|
||||
- ua-slack
|
||||
- ua-googledocs
|
||||
- js-whatsapp-web
|
||||
- js-discord
|
||||
|
|
@ -752,7 +750,7 @@ content.headers.referer:
|
|||
content.headers.user_agent:
|
||||
default: 'Mozilla/5.0 ({os_info})
|
||||
AppleWebKit/{webkit_version} (KHTML, like Gecko)
|
||||
{qt_key}/{qt_version} {upstream_browser_key}/{upstream_browser_version_short}
|
||||
{upstream_browser_key}/{upstream_browser_version_short}
|
||||
Safari/{webkit_version}'
|
||||
type:
|
||||
name: FormatString
|
||||
|
|
@ -800,12 +798,11 @@ content.headers.user_agent:
|
|||
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.
|
||||
|
||||
content.host_blocking.enabled:
|
||||
renamed: content.blocking.enabled
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ def qt_args(namespace: argparse.Namespace) -> list[str]:
|
|||
return argv
|
||||
|
||||
|
||||
def _qtwebengine_features(
|
||||
def _qtwebengine_features( # noqa: C901
|
||||
versions: version.WebEngineVersions,
|
||||
special_flags: Sequence[str],
|
||||
) -> tuple[Sequence[str], Sequence[str]]:
|
||||
|
|
@ -159,6 +159,11 @@ def _qtwebengine_features(
|
|||
# TODO adjust if fixed in Qt 6.8.2/.3 or 6.9.0/.1
|
||||
disabled_features.append('DocumentPictureInPictureAPI')
|
||||
|
||||
if versions.webengine == utils.VersionNumber(6, 9):
|
||||
# WORKAROUND for https://bugreports.qt.io/browse/QTBUG-135787
|
||||
# TODO adjust if still present in 6.9.1
|
||||
disabled_features.append('PermissionElement')
|
||||
|
||||
if not config.val.input.media_keys:
|
||||
disabled_features.append('HardwareMediaKeyHandling')
|
||||
|
||||
|
|
|
|||
|
|
@ -19,4 +19,16 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
return { promise, resolve, reject }
|
||||
}
|
||||
}
|
||||
|
||||
// Chromium 126 / QtWebEngine 6.9
|
||||
// https://caniuse.com/mdn-api_url_parse_static
|
||||
if (typeof URL.parse === "undefined") {
|
||||
URL.parse = function(url, base) {
|
||||
try {
|
||||
return new URL(url, base);
|
||||
} catch (ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -172,12 +172,14 @@ def debug_flag_error(flag):
|
|||
werror: Turn Python warnings into errors.
|
||||
test-notification-service: Use the testing libnotify service.
|
||||
caret: Enable debug logging for caret.js.
|
||||
no-system-pdfjs: Ignore system-wide PDF.js installations
|
||||
"""
|
||||
valid_flags = ['debug-exit', 'pdb-postmortem', 'no-sql-history',
|
||||
'no-scroll-filtering', 'log-requests', 'log-cookies',
|
||||
'log-scroll-pos', 'log-sensitive-keys', 'stack', 'chromium',
|
||||
'wait-renderer-process', 'avoid-chromium-init', 'werror',
|
||||
'test-notification-service', 'log-qt-events', 'caret']
|
||||
'test-notification-service', 'log-qt-events', 'caret',
|
||||
'no-system-pdfjs']
|
||||
|
||||
if flag in valid_flags:
|
||||
return flag
|
||||
|
|
|
|||
|
|
@ -639,8 +639,9 @@ class WebEngineVersions:
|
|||
utils.VersionNumber(6, 8): (_BASES[122], '129.0.6668.70'), # 2024-09-24
|
||||
utils.VersionNumber(6, 8, 1): (_BASES[122], '131.0.6778.70'), # 2024-11-12
|
||||
utils.VersionNumber(6, 8, 2): (_BASES[122], '132.0.6834.111'), # 2025-01-22
|
||||
utils.VersionNumber(6, 8, 3): (_BASES[122], '134.0.6998.89'), # 2025-03-10
|
||||
|
||||
## Qt 6.9 (Beta 3)
|
||||
## Qt 6.9
|
||||
utils.VersionNumber(6, 9): (_BASES[130], '133.0.6943.141'), # 2025-02-25
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
"types-docutils": "https://github.com/python/typeshed/commits/main/stubs/docutils",
|
||||
"types-Pygments": "https://github.com/python/typeshed/commits/main/stubs/Pygments",
|
||||
"pytest": "https://docs.pytest.org/en/latest/changelog.html",
|
||||
"iniconfig": "https://github.com/pytest-dev/iniconfig/blob/master/CHANGELOG",
|
||||
"iniconfig": "https://github.com/pytest-dev/iniconfig/blob/main/CHANGELOG",
|
||||
"tox": "https://tox.readthedocs.io/en/latest/changelog.html",
|
||||
"cachetools": "https://github.com/tkem/cachetools/blob/master/CHANGELOG.rst",
|
||||
"pyproject-api": "https://github.com/tox-dev/pyproject-api/releases",
|
||||
|
|
@ -92,7 +92,7 @@
|
|||
"pydantic": "https://docs.pydantic.dev/latest/changelog/",
|
||||
"pydantic-settings": "https://github.com/pydantic/pydantic-settings/releases",
|
||||
"pydantic_core": "https://github.com/pydantic/pydantic-core/releases",
|
||||
"python-dotenv": "https://saurabh-kumar.com/python-dotenv/changelog/",
|
||||
"python-dotenv": "https://github.com/theskumar/python-dotenv/blob/main/CHANGELOG.md",
|
||||
"questionary": "https://github.com/tmbo/questionary/blob/master/docs/pages/changelog.rst",
|
||||
"rich-click": "https://ewels.github.io/rich-click/changelog/",
|
||||
"wcmatch": "https://github.com/facelessuser/wcmatch/releases",
|
||||
|
|
@ -133,6 +133,7 @@
|
|||
"idna": "https://github.com/kjd/idna/blob/master/HISTORY.rst",
|
||||
"tldextract": "https://github.com/john-kurkowski/tldextract/blob/master/CHANGELOG.md",
|
||||
"typing_extensions": "https://github.com/python/typing_extensions/blob/main/CHANGELOG.md",
|
||||
"typing-inspection": "https://github.com/pydantic/typing-inspection/blob/main/HISTORY.md",
|
||||
"diff_cover": "https://github.com/Bachmann1234/diff_cover/blob/main/CHANGELOG",
|
||||
"beautifulsoup4": "https://git.launchpad.net/beautifulsoup/tree/CHANGELOG",
|
||||
"check-manifest": "https://github.com/mgedmin/check-manifest/blob/master/CHANGES.rst",
|
||||
|
|
|
|||
2
setup.py
2
setup.py
|
|
@ -72,8 +72,6 @@ try:
|
|||
'Development Status :: 5 - Production/Stable',
|
||||
'Environment :: X11 Applications :: Qt',
|
||||
'Intended Audience :: End Users/Desktop',
|
||||
'License :: OSI Approved :: GNU General Public License v3 or later '
|
||||
'(GPLv3+)',
|
||||
'Natural Language :: English',
|
||||
'Operating System :: Microsoft :: Windows',
|
||||
'Operating System :: POSIX :: Linux',
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ def _apply_platform_markers(config, item):
|
|||
"Failing due to cheroot: https://github.com/cherrypy/cheroot/issues/346"),
|
||||
(
|
||||
"qt69_ci_flaky", # WORKAROUND: https://github.com/qutebrowser/qutebrowser/issues/8444#issuecomment-2569610110
|
||||
pytest.mark.flaky,
|
||||
pytest.mark.flaky(reruns=3),
|
||||
(
|
||||
config.webengine
|
||||
and version.qtwebengine_versions(avoid_init=True).webengine
|
||||
|
|
@ -137,6 +137,17 @@ def _apply_platform_markers(config, item):
|
|||
),
|
||||
"Flaky with QtWebEngine 6.9 on CI",
|
||||
),
|
||||
(
|
||||
"qt69_ci_skip", # WORKAROUND: https://github.com/qutebrowser/qutebrowser/issues/8444#issuecomment-2569610110
|
||||
pytest.mark.skipif,
|
||||
(
|
||||
config.webengine
|
||||
and version.qtwebengine_versions(avoid_init=True).webengine
|
||||
== utils.VersionNumber(6, 9)
|
||||
and testutils.ON_CI
|
||||
),
|
||||
"Skipped with QtWebEngine 6.9 on CI",
|
||||
),
|
||||
]
|
||||
|
||||
for searched_marker, new_marker_kind, condition, default_reason in markers:
|
||||
|
|
|
|||
|
|
@ -303,14 +303,14 @@ Feature: Special qute:// pages
|
|||
|
||||
# :version
|
||||
|
||||
@qt69_ci_flaky
|
||||
@qt69_ci_skip
|
||||
Scenario: Open qute://version
|
||||
When I open qute://version
|
||||
Then the page should contain the plaintext "Version info"
|
||||
|
||||
# qute://gpl
|
||||
|
||||
@qt69_ci_flaky
|
||||
@qt69_ci_skip
|
||||
Scenario: Open qute://gpl
|
||||
When I open qute://gpl
|
||||
Then the page should contain the plaintext "GNU GENERAL PUBLIC LICENSE"
|
||||
|
|
@ -318,7 +318,7 @@ Feature: Special qute:// pages
|
|||
# qute://start
|
||||
|
||||
# QtWebKit doesn't support formaction; unknown Qt 6.9 renderer process crashes
|
||||
@qtwebkit_skip @qt69_ci_flaky
|
||||
@qtwebkit_skip @qt69_ci_skip
|
||||
Scenario: Searching on qute://start
|
||||
When I set url.searchengines to {"DEFAULT": "http://localhost:(port)/data/title.html?q={}"}
|
||||
And I open qute://start
|
||||
|
|
|
|||
|
|
@ -1659,14 +1659,16 @@ Feature: Tab management
|
|||
When I set tabs.last_close to close
|
||||
And I run :tab-only
|
||||
And I run :tab-close ;; tab-next
|
||||
Then qutebrowser should quit
|
||||
Then the error "No WebView available yet!" should be shown
|
||||
And qutebrowser should quit
|
||||
And no crash should happen
|
||||
|
||||
Scenario: Using :tab-prev after closing last tab (#1448)
|
||||
When I set tabs.last_close to close
|
||||
And I run :tab-only
|
||||
And I run :tab-close ;; tab-prev
|
||||
Then qutebrowser should quit
|
||||
Then the error "No WebView available yet!" should be shown
|
||||
And qutebrowser should quit
|
||||
And no crash should happen
|
||||
|
||||
Scenario: Opening link with tabs_are_windows set (#2162)
|
||||
|
|
|
|||
|
|
@ -131,6 +131,8 @@ def is_ignored_chromium_message(line):
|
|||
# Qt 6.2:
|
||||
# [503633:503650:0509/185222.442798:ERROR:ssl_client_socket_impl.cc(959)] handshake failed; returned -1, SSL error code 1, net_error -202
|
||||
'handshake failed; returned -1, SSL error code 1, net_error -202',
|
||||
# Qt 6.8 + Python 3.14
|
||||
'handshake failed; returned -1, SSL error code 1, net_error -101',
|
||||
|
||||
# Qt 6.2:
|
||||
# [2432160:7:0429/195800.168435:ERROR:command_buffer_proxy_impl.cc(140)] ContextResult::kTransientFailure: Failed to send GpuChannelMsg_CreateCommandBuffer.
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ class WSGIServer(cheroot.wsgi.Server):
|
|||
|
||||
def unraisable_hook(unraisable: "sys.UnraisableHookArgs") -> None:
|
||||
if (
|
||||
sys.version_info[:2] == (3, 13)
|
||||
sys.version_info[:2] >= (3, 13)
|
||||
and isinstance(unraisable.exc_value, OSError)
|
||||
and (
|
||||
unraisable.exc_value.errno == errno.EBADF
|
||||
|
|
@ -351,7 +351,19 @@ def unraisable_hook(unraisable: "sys.UnraisableHookArgs") -> None:
|
|||
and unraisable.exc_value.winerror == errno.WSAENOTSOCK
|
||||
)
|
||||
)
|
||||
and unraisable.object.__qualname__ == "IOBase.__del__"
|
||||
and (
|
||||
(
|
||||
# Python 3.14
|
||||
unraisable.object is None
|
||||
and unraisable.err_msg.startswith(
|
||||
"Exception ignored while calling deallocator <function IOBase.__del__ at "
|
||||
)
|
||||
)
|
||||
or (
|
||||
unraisable.object is not None
|
||||
and unraisable.object.__qualname__ == "IOBase.__del__"
|
||||
)
|
||||
)
|
||||
):
|
||||
# WORKAROUND for bogus exceptions with cheroot:
|
||||
# https://github.com/cherrypy/cheroot/issues/734
|
||||
|
|
|
|||
|
|
@ -56,9 +56,25 @@ def test_auto_load(quteproc, auto_load, background, insert_mode):
|
|||
quteproc.ensure_not_logged(message=log_message)
|
||||
|
||||
|
||||
def test_auto_load_delayed_tab_close(quteproc):
|
||||
"""We shouldn't try to run JS on dead tabs async.
|
||||
|
||||
Triggering the bug is pretty timing-dependent, so this test might still pass
|
||||
even if a bug is present. Howevber, with those timings, it triggers consistently
|
||||
on my machine.
|
||||
"""
|
||||
quteproc.set_setting('input.insert_mode.auto_load', "true")
|
||||
quteproc.send_cmd(":cmd-later 50 open -t about:blank")
|
||||
quteproc.send_cmd(":cmd-later 110 tab-close")
|
||||
quteproc.wait_for(message="command called: tab-close")
|
||||
|
||||
|
||||
def test_auto_leave_insert_mode(quteproc):
|
||||
quteproc.set_setting('input.insert_mode.auto_load', 'true')
|
||||
|
||||
url_path = 'data/insert_mode_settings/html/autofocus.html'
|
||||
quteproc.open_path(url_path)
|
||||
quteproc.wait_for(message='Entering mode KeyMode.insert (reason: *)')
|
||||
|
||||
quteproc.set_setting('input.insert_mode.auto_leave', 'true')
|
||||
quteproc.send_cmd(':zoom 100')
|
||||
|
|
|
|||
|
|
@ -277,7 +277,7 @@ DISABLE_SECCOMP_BPF_FLAG = "--disable-seccomp-filter-sandbox"
|
|||
DISABLE_SECCOMP_BPF_ARGS = ["-s", "qt.chromium.sandboxing", "disable-seccomp-bpf"]
|
||||
|
||||
|
||||
def _needs_map_discard_workaround(webengine_version: utils.VersionNumber) -> bool:
|
||||
def _needs_map_discard_workaround(qtwe_version: utils.VersionNumber) -> bool:
|
||||
"""Check if this system needs the glibc 2.41+ MAP_DISCARD workaround.
|
||||
|
||||
WORKAROUND for https://bugreports.qt.io/browse/QTBUG-134631
|
||||
|
|
@ -286,9 +286,6 @@ def _needs_map_discard_workaround(webengine_version: utils.VersionNumber) -> boo
|
|||
if not utils.is_posix:
|
||||
return False
|
||||
|
||||
# Not fixed yet as of Qt 6.9 Beta 3
|
||||
utils.unused(webengine_version)
|
||||
|
||||
libc_name, libc_version_str = platform.libc_ver()
|
||||
if libc_name != "glibc":
|
||||
return False
|
||||
|
|
@ -300,7 +297,21 @@ def _needs_map_discard_workaround(webengine_version: utils.VersionNumber) -> boo
|
|||
affected_glibc = utils.VersionNumber(2, 41)
|
||||
affected_kernel = utils.VersionNumber(6, 11)
|
||||
|
||||
return libc_version >= affected_glibc and kernel_version >= affected_kernel
|
||||
return (
|
||||
libc_version >= affected_glibc
|
||||
and kernel_version >= affected_kernel
|
||||
and not (
|
||||
# https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/631749
|
||||
# -> Fixed in QtWebEngine 5.15.9
|
||||
utils.VersionNumber(5, 15, 19) <= qtwe_version < utils.VersionNumber(6)
|
||||
# https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/631750
|
||||
# -> Fixed in QtWebEngine 6.8.4
|
||||
or utils.VersionNumber(6, 8, 4) <= qtwe_version < utils.VersionNumber(6, 9)
|
||||
# https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/631348
|
||||
# -> Fixed in QtWebEngine 6.9.1
|
||||
or utils.VersionNumber(6, 9, 1) <= qtwe_version
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def disable_seccomp_bpf_sandbox() -> bool:
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@ from qutebrowser.browser import downloads, qtnetworkdownloads
|
|||
@pytest.fixture
|
||||
def manager(config_stub, cookiejar_and_cache):
|
||||
"""A QtNetwork download manager."""
|
||||
return qtnetworkdownloads.DownloadManager()
|
||||
dl_manager = qtnetworkdownloads.DownloadManager()
|
||||
yield dl_manager
|
||||
dl_manager.deleteLater()
|
||||
|
||||
|
||||
def test_download_model(qapp, qtmodeltester, manager):
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import logging
|
||||
import pathlib
|
||||
import unittest.mock
|
||||
import os.path
|
||||
|
||||
import pytest
|
||||
|
|
@ -10,6 +12,7 @@ from qutebrowser.qt.core import QUrl
|
|||
|
||||
from qutebrowser.browser import pdfjs
|
||||
from qutebrowser.utils import urlmatch, utils
|
||||
from qutebrowser.misc import objects
|
||||
|
||||
|
||||
pytestmark = [pytest.mark.usefixtures('data_tmpdir')]
|
||||
|
|
@ -73,20 +76,32 @@ class TestResources:
|
|||
read_system_mock.assert_called_with('/usr/share/pdf.js/',
|
||||
['web/test', 'test'])
|
||||
|
||||
def test_get_pdfjs_res_bundled(self, read_system_mock, read_file_mock,
|
||||
tmpdir):
|
||||
@pytest.mark.parametrize("with_system", [True, False])
|
||||
def test_get_pdfjs_res_bundled(
|
||||
self,
|
||||
read_system_mock: unittest.mock.Mock,
|
||||
read_file_mock: unittest.mock.Mock,
|
||||
tmp_path: pathlib.Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
with_system: bool,
|
||||
) -> None:
|
||||
read_system_mock.return_value = (None, None)
|
||||
|
||||
read_file_mock.return_value = b'content'
|
||||
if not with_system:
|
||||
monkeypatch.setattr(objects, 'debug_flags', {'no-system-pdfjs'})
|
||||
|
||||
assert pdfjs.get_pdfjs_res_and_path('web/test') == (b'content', None)
|
||||
assert pdfjs.get_pdfjs_res('web/test') == b'content'
|
||||
|
||||
for path in ['/usr/share/pdf.js/',
|
||||
str(tmpdir / 'data' / 'pdfjs'),
|
||||
# hardcoded for --temp-basedir
|
||||
os.path.expanduser('~/.local/share/qutebrowser/pdfjs/')]:
|
||||
read_system_mock.assert_any_call(path, ['web/test', 'test'])
|
||||
paths = {call.args[0] for call in read_system_mock.mock_calls}
|
||||
expected_paths = {
|
||||
str(tmp_path / 'data' / 'pdfjs'),
|
||||
# hardcoded for --temp-basedir
|
||||
os.path.expanduser('~/.local/share/qutebrowser/pdfjs/')
|
||||
}
|
||||
assert expected_paths.issubset(paths)
|
||||
if not with_system:
|
||||
assert '/usr/share/pdf.js/' not in paths
|
||||
|
||||
def test_get_pdfjs_res_not_found(self, read_system_mock, read_file_mock,
|
||||
caplog):
|
||||
|
|
|
|||
|
|
@ -105,7 +105,6 @@ def assert_none_blocked(ad_blocker):
|
|||
assert_urls(ad_blocker, NOT_OKAY_URLS + OKAY_URLS, False)
|
||||
|
||||
def assert_not_blocked(url, source_url, resource_type):
|
||||
nonlocal ad_blocker
|
||||
assert not ad_blocker._is_blocked(url, source_url, resource_type)
|
||||
|
||||
run_function_on_dataset(assert_not_blocked)
|
||||
|
|
|
|||
|
|
@ -787,7 +787,6 @@ class TestYamlMigrations:
|
|||
@pytest.mark.parametrize('old, new', [
|
||||
(None, ('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}')),
|
||||
('toaster', 'toaster'),
|
||||
|
|
|
|||
|
|
@ -448,25 +448,25 @@ class TestWebEngineArgs:
|
|||
expected = ['--disable-features=InstalledApp'] if has_workaround else []
|
||||
assert disable_features_args == expected
|
||||
|
||||
@pytest.mark.parametrize('qt_version, has_workaround', [
|
||||
@pytest.mark.parametrize('qt_version, disabled', [
|
||||
# Qt 6.6
|
||||
('6.6.3', False),
|
||||
('6.6.3', None),
|
||||
# Qt 6.7
|
||||
('6.7.0', True),
|
||||
('6.7.1', True),
|
||||
('6.7.2', True),
|
||||
('6.7.3', True),
|
||||
('6.7.0', "DocumentPictureInPictureAPI"),
|
||||
('6.7.1', "DocumentPictureInPictureAPI"),
|
||||
('6.7.2', "DocumentPictureInPictureAPI"),
|
||||
('6.7.3', "DocumentPictureInPictureAPI"),
|
||||
# Qt 6.8
|
||||
('6.8.0', True),
|
||||
('6.8.1', True),
|
||||
('6.8.2', True), # tbd
|
||||
('6.8.3', True), # tbd
|
||||
('6.8.0', "DocumentPictureInPictureAPI"),
|
||||
('6.8.1', "DocumentPictureInPictureAPI"),
|
||||
('6.8.2', "DocumentPictureInPictureAPI"),
|
||||
('6.8.3', "DocumentPictureInPictureAPI"),
|
||||
# Qt 6.9
|
||||
('6.9.0', True), # tbd
|
||||
('6.9.1', True), # tbd
|
||||
('6.9.0', "DocumentPictureInPictureAPI,PermissionElement"),
|
||||
('6.9.1', "DocumentPictureInPictureAPI"), # tbd
|
||||
])
|
||||
def test_document_pip_workaround(
|
||||
self, parser, version_patcher, qt_version, has_workaround
|
||||
def test_disble_feature_workaround(
|
||||
self, parser, version_patcher, qt_version, disabled
|
||||
):
|
||||
version_patcher(qt_version)
|
||||
|
||||
|
|
@ -477,8 +477,7 @@ class TestWebEngineArgs:
|
|||
if arg.startswith(qtargs._DISABLE_FEATURES)
|
||||
]
|
||||
|
||||
flag = "--disable-features=DocumentPictureInPictureAPI"
|
||||
expected = [flag] if has_workaround else []
|
||||
expected = [f"--disable-features={disabled}"] if disabled else []
|
||||
assert disable_features_args == expected
|
||||
|
||||
@pytest.mark.parametrize('enabled', [True, False])
|
||||
|
|
|
|||
|
|
@ -61,17 +61,17 @@ def test_js_quirks_match_files(webengine_tab):
|
|||
|
||||
|
||||
def test_js_quirks_match_settings(webengine_tab, configdata_init):
|
||||
quirks_code = {q.name for q in webengine_tab._scripts._get_quirks()}
|
||||
|
||||
opt = configdata.DATA["content.site_specific_quirks.skip"]
|
||||
prefix = "js-"
|
||||
valid_values = opt.typ.get_valid_values()
|
||||
assert valid_values is not None
|
||||
quirks_config = {
|
||||
val.removeprefix(prefix).replace("-", "_")
|
||||
val
|
||||
for val in valid_values
|
||||
if val.startswith(prefix)
|
||||
# some JS quirks are actually only setting the user agent, so we include
|
||||
# those as well.
|
||||
if val.startswith("js-") or (val.startswith("ua-") and val in quirks_code)
|
||||
}
|
||||
|
||||
quirks_code = {q.filename for q in webengine_tab._scripts._get_quirks()}
|
||||
quirks_code -= {"googledocs"} # special case, UA quirk
|
||||
|
||||
assert quirks_code == quirks_config
|
||||
|
|
|
|||
|
|
@ -530,7 +530,7 @@ class TestSavefileOpen:
|
|||
assert data == b'foo\nbar\nbaz'
|
||||
|
||||
|
||||
if test_file is not None:
|
||||
if test_file is not None: # noqa: C901
|
||||
# If we were able to import Python's test_file module, we run some code
|
||||
# here which defines unittest TestCases to run the python tests over
|
||||
# PyQIODevice.
|
||||
|
|
@ -577,7 +577,7 @@ if test_file is not None:
|
|||
qiodev.name = test_file.TESTFN
|
||||
qiodev.mode = mode
|
||||
# Create empty TESTFN file because the Python tests try to unlink
|
||||
# it.after the test.
|
||||
# it after the test.
|
||||
with open(test_file.TESTFN, 'w', encoding='utf-8'):
|
||||
pass
|
||||
return qiodev
|
||||
|
|
@ -598,6 +598,9 @@ if test_file is not None:
|
|||
def testSetBufferSize(self):
|
||||
"""Skip this test as setting buffer size is unsupported."""
|
||||
|
||||
def testDefaultBufferSize(self):
|
||||
"""Skip this test as getting buffer size is unsupported."""
|
||||
|
||||
def testTruncateOnWindows(self):
|
||||
"""Skip this test truncating is unsupported."""
|
||||
|
||||
|
|
|
|||
4
tox.ini
4
tox.ini
|
|
@ -41,6 +41,7 @@ basepython =
|
|||
py311: {env:PYTHON:python3.11}
|
||||
py312: {env:PYTHON:python3.12}
|
||||
py313: {env:PYTHON:python3.13}
|
||||
py314: {env:PYTHON:python3.14}
|
||||
deps =
|
||||
-r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/misc/requirements/requirements-tests.txt
|
||||
|
|
@ -55,8 +56,9 @@ deps =
|
|||
pyqt66: -r{toxinidir}/misc/requirements/requirements-pyqt-6.6.txt
|
||||
pyqt67: -r{toxinidir}/misc/requirements/requirements-pyqt-6.7.txt
|
||||
pyqt68: -r{toxinidir}/misc/requirements/requirements-pyqt-6.8.txt
|
||||
pyqt69: -r{toxinidir}/misc/requirements/requirements-pyqt-6.9.txt
|
||||
commands =
|
||||
!pyqt-!pyqt515-!pyqt5152-!pyqt62-!pyqt63-!pyqt64-!pyqt65-!pyqt66-!pyqt67-!pyqt68: {envpython} scripts/link_pyqt.py --tox {envdir}
|
||||
!pyqt-!pyqt515-!pyqt5152-!pyqt62-!pyqt63-!pyqt64-!pyqt65-!pyqt66-!pyqt67-!pyqt68-!pyqt69: {envpython} scripts/link_pyqt.py --tox {envdir}
|
||||
{envpython} -bb -m pytest {posargs:tests}
|
||||
cov: {envpython} scripts/dev/check_coverage.py {posargs}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue