summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.flake86
-rw-r--r--.github/workflows/ci.yml6
-rw-r--r--.mypy.ini2
-rw-r--r--.pylintrc2
-rw-r--r--README.asciidoc11
-rw-r--r--doc/changelog.asciidoc14
-rw-r--r--doc/contributing.asciidoc19
-rw-r--r--doc/help/configuring.asciidoc4
-rw-r--r--doc/install.asciidoc4
-rw-r--r--misc/requirements/requirements-dev.txt11
-rw-r--r--misc/requirements/requirements-mypy.txt3
-rw-r--r--misc/requirements/requirements-mypy.txt-raw1
-rw-r--r--misc/requirements/requirements-pylint.txt5
-rw-r--r--misc/requirements/requirements-pylint.txt-raw4
-rw-r--r--misc/requirements/requirements-qutebrowser.txt-raw13
-rw-r--r--misc/requirements/requirements-sphinx.txt2
-rw-r--r--misc/requirements/requirements-tests.txt45
-rw-r--r--misc/requirements/requirements-tests.txt-raw32
-rw-r--r--misc/requirements/requirements-tox.txt12
-rw-r--r--misc/requirements/requirements-tox.txt-raw10
-rwxr-xr-xmisc/userscripts/qute-bitwarden16
-rwxr-xr-xmisc/userscripts/qute-lastpass2
-rw-r--r--qutebrowser/browser/webkit/http.py1
-rw-r--r--qutebrowser/completion/models/filepathcategory.py2
-rw-r--r--qutebrowser/components/braveadblock.py5
-rw-r--r--qutebrowser/misc/checkpyver.py4
-rw-r--r--qutebrowser/misc/earlyinit.py3
-rw-r--r--qutebrowser/utils/utils.py23
-rw-r--r--requirements.txt12
-rwxr-xr-xscripts/dev/build_release.py9
-rw-r--r--scripts/dev/changelog_urls.json7
-rw-r--r--scripts/dev/check_coverage.py4
-rw-r--r--scripts/dev/misc_checks.py2
-rw-r--r--scripts/dev/recompile_requirements.py5
-rw-r--r--scripts/dev/run_pylint_on_tests.py3
-rwxr-xr-xscripts/dev/update_3rdparty.py41
-rw-r--r--scripts/link_pyqt.py4
-rwxr-xr-xscripts/mkvenv.py2
-rw-r--r--scripts/setupcommon.py2
-rwxr-xr-xsetup.py4
-rw-r--r--tests/end2end/test_invocations.py4
-rw-r--r--tests/unit/config/test_configtypes.py9
-rw-r--r--tests/unit/misc/test_checkpyver.py7
-rw-r--r--tests/unit/misc/userscripts/test_qute_lastpass.py12
-rw-r--r--tests/unit/utils/test_standarddir.py2
-rw-r--r--tests/unit/utils/test_utils.py2
-rw-r--r--tox.ini1
47 files changed, 156 insertions, 238 deletions
diff --git a/.flake8 b/.flake8
index 9110dc54c..34a829a4b 100644
--- a/.flake8
+++ b/.flake8
@@ -40,7 +40,7 @@ exclude = .*,__pycache__,resources.py
# A003: Builtin name for class attribute (needed for overridden methods)
# W503: like break before binary operator
# W504: line break after binary operator
-# FI15: __future__ import "generator_stop" missing
+# FI18: __future__ import "annotations" missing
# 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
@@ -53,11 +53,11 @@ ignore =
D102,D103,D106,D107,D104,D105,D209,D211,D401,D402,D403,D412,D413,
A003,
W503, W504,
- FI15,
+ FI18,
PT004,
PT011,
PT012
-min-version = 3.6.1
+min-version = 3.7.0
max-complexity = 12
per-file-ignores =
qutebrowser/api/hook.py : N801
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index afcf720e4..06863ab10 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -105,10 +105,10 @@ jobs:
fail-fast: false
matrix:
include:
- ### PyQt 5.12 (Python 3.6)
- - testenv: py36-pyqt512
+ ### PyQt 5.12 (Python 3.7)
+ - testenv: py37-pyqt512
os: ubuntu-18.04
- python: 3.6
+ python: 3.7
### PyQt 5.13 (Python 3.7)
- testenv: py37-pyqt513
os: ubuntu-20.04
diff --git a/.mypy.ini b/.mypy.ini
index 501ab747e..b347323f5 100644
--- a/.mypy.ini
+++ b/.mypy.ini
@@ -1,5 +1,5 @@
[mypy]
-python_version = 3.6
+python_version = 3.7
### --strict
warn_unused_configs = True
diff --git a/.pylintrc b/.pylintrc
index 4ff4f2080..c5a1289fb 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -18,7 +18,7 @@ load-plugins=qute_pylint.config,
pylint.extensions.private_import,
persistent=n
-py-version=3.6
+py-version=3.7
[MESSAGES CONTROL]
enable=all
diff --git a/README.asciidoc b/README.asciidoc
index d1bb9ee98..5ac14c418 100644
--- a/README.asciidoc
+++ b/README.asciidoc
@@ -74,7 +74,7 @@ Requirements
The following software and libraries are required to run qutebrowser:
-* https://www.python.org/[Python] 3.6.1 or newer
+* https://www.python.org/[Python] 3.7 or newer
* https://www.qt.io/[Qt] 5.12.0 or newer (5.12 LTS or 5.15 recommended, Qt 6 is
not supported yet) with the following modules:
- QtCore / qtbase
@@ -96,10 +96,9 @@ websites and using it for transmission of sensitive data._
* https://palletsprojects.com/p/jinja/[jinja2]
* https://github.com/yaml/pyyaml[PyYAML]
-On older Python versions (3.6/3.7/3.8), the following backports are also required:
+On older Python versions (3.7/3.8), the following backports are also required:
-* https://importlib-resources.readthedocs.io/[importlib_resources] (Python 3.8 or older)
-* https://github.com/ericvsmith/dataclasses[dataclasses] (Python 3.6 only)
+* https://importlib-resources.readthedocs.io/[importlib_resources]
The following libraries are optional:
@@ -109,8 +108,8 @@ The following libraries are optional:
QtWebEngine backend.
* On Windows, https://pypi.python.org/pypi/colorama/[colorama] for colored log
output.
-* https://importlib-metadata.readthedocs.io/[importlib_resources] on Python 3.7
- or older, to improve QtWebEngine version detection when PyQtWebEngine is
+* https://importlib-metadata.readthedocs.io/[importlib_metadata] on Python 3.7,
+ to improve QtWebEngine version detection when PyQtWebEngine is
installed via pip (thus, this dependency usually isn't relevant for
packagers).
* https://asciidoc.org/[asciidoc] to generate the documentation for the `:help`
diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc
index 1dbc4d771..236039f67 100644
--- a/doc/changelog.asciidoc
+++ b/doc/changelog.asciidoc
@@ -22,10 +22,12 @@ v3.0.0 (unreleased)
Removed
~~~~~~~
+- Support for Python 3.6 is dropped, as it's been
+ https://discuss.python.org/t/python-3-6-rides-into-the-sunset/12964[end-of-life upstream]
+ since December 2021. Python 3.7.0 or newer is now required.
- It's planned to drop support for various legacy platforms and libraries which
are unsupported upstream, such as:
* Qt before 5.15 LTS (plus adding support for Qt 6.2+)
- * Python 3.6
* The QtWebKit backend
* macOS 10.14 (via Homebrew)
* 32-bit Windows (via Qt)
@@ -33,6 +35,15 @@ Removed
* Windows 10 before 1809 (via Qt)
* Possibly other more minor dependency changes
+Changed
+~~~~~~~
+
+- The qutebrowser icons got moved from `icons/` to `qutebrowser/icons` in the
+ repository, so that it's possible for qutebrowser to load them using Python's
+ resource system (rather than compiling them into a Qt resource file).
+ Packagers are advised to use `misc/Makefile` if possible, which has been
+ updated with the new paths.
+
[[v2.5.1]]
v2.5.1 (unreleased)
-------------------
@@ -41,6 +52,7 @@ Fixed
~~~~~
- The `qute-pass` userscript is marked as executable again.
+- PDF.js now works properly again with the macOS and Windows releases.
[[v2.5.0]]
v2.5.0 (2022-04-01)
diff --git a/doc/contributing.asciidoc b/doc/contributing.asciidoc
index 75c19045e..70447d8c5 100644
--- a/doc/contributing.asciidoc
+++ b/doc/contributing.asciidoc
@@ -111,9 +111,9 @@ unittests and several linters/checkers.
Currently, the following tox environments are available:
* Tests using https://www.pytest.org[pytest]:
- - `py36`, `py37`, ...: Run pytest for python 3.6/3.7/... with the system-wide PyQt.
- - `py36-pyqt512`, ..., `py36-pyqt515`: Run pytest with the given PyQt version (`py35-*` also works).
- - `py36-pyqt515-cov`: Run with coverage support (other Python/PyQt versions work too).
+ - `py37`, `py38`, ...: Run pytest for python 3.7/3.8/... with the system-wide PyQt.
+ - `py37-pyqt512`, ..., `py37-pyqt515`: Run pytest with the given PyQt version (`py37-*` also works).
+ - `py37-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.
@@ -168,16 +168,16 @@ Examples:
----
# run only pytest tests which failed in last run:
-tox -e py35 -- --lf
+tox -e py37 -- --lf
# run only the end2end feature tests:
-tox -e py35 -- tests/end2end/features
+tox -e py37 -- tests/end2end/features
# run everything with undo in the generated name, based on the scenario text
-tox -e py35 -- tests/end2end/features/test_tabs_bdd.py -k undo
+tox -e py37 -- tests/end2end/features/test_tabs_bdd.py -k undo
# run coverage test for specific file (updates htmlcov/index.html)
-tox -e py35-cov -- tests/unit/browser/test_webelem.py
+tox -e py37-cov -- tests/unit/browser/test_webelem.py
----
Profiling
@@ -544,11 +544,8 @@ ____
Setting up a Windows Development Environment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-* Install https://www.python.org/downloads/release/python-362/[Python 3.6].
+* Install https://www.python.org/downloads/release/python-3911/[Python 3.9].
* Install PyQt via `pip install PyQt5`.
-* Create a file at `C:\Windows\system32\python3.bat` with the following content (adjust the path as necessary):
- `@C:\Python36\python %*`.
- This will make the Python 3.6 interpreter available as `python3`, which is used by various development scripts.
* Install git from the https://git-scm.com/download/win[git-scm downloads page].
Try not to enable `core.autocrlf`, since that will cause `flake8` to complain a lot. Use an editor that can deal with plain line feeds instead.
* Clone your favourite qutebrowser repository.
diff --git a/doc/help/configuring.asciidoc b/doc/help/configuring.asciidoc
index a59f48130..3ecef8ecf 100644
--- a/doc/help/configuring.asciidoc
+++ b/doc/help/configuring.asciidoc
@@ -391,8 +391,8 @@ import subprocess
def read_xresources(prefix):
props = {}
- x = subprocess.run(['xrdb', '-query'], stdout=subprocess.PIPE)
- lines = x.stdout.decode().split('\n')
+ x = subprocess.run(['xrdb', '-query'], capture_output=True, check=True, text=True)
+ lines = x.stdout.split('\n')
for line in filter(lambda l : l.startswith(prefix), lines):
prop, _, value = line.partition(':\t')
props[prop] = value
diff --git a/doc/install.asciidoc b/doc/install.asciidoc
index dd284fb9a..bb4e08f5a 100644
--- a/doc/install.asciidoc
+++ b/doc/install.asciidoc
@@ -38,7 +38,7 @@ version (Qt 5.7, based on a Chromium from March 2016). Furthermore, it packages
Ubuntu 16.04 doesn't come with an up-to-date engine (a new enough QtWebKit, or
QtWebEngine) and also comes with Python 3.5.
-You should be able to install a newer Python (3.6+) using the
+You should be able to install a newer Python (3.7+) using the
https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa[deadsnakes PPA] or
https://github.com/pyenv/pyenv[pyenv], and then proceed to
<<tox,install qutebrowser in a virtualenv>>. However, this is currently untested. If you
@@ -447,7 +447,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.6 or newer, otherwise you'll get a "No
+- Make sure your `python3` is Python 3.7 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.
diff --git a/misc/requirements/requirements-dev.txt b/misc/requirements/requirements-dev.txt
index 9f7f5074b..ba9b73dc6 100644
--- a/misc/requirements/requirements-dev.txt
+++ b/misc/requirements/requirements-dev.txt
@@ -6,14 +6,14 @@ bump2version==1.0.1
certifi==2021.10.8
cffi==1.15.0
charset-normalizer==2.0.12
-colorama==0.4.4
+commonmark==0.9.1
cryptography==36.0.2
docutils==0.18.1
github3.py==3.2.0
hunter==3.4.3
idna==3.3
importlib-metadata==4.11.3
-jeepney==0.7.1
+jeepney==0.8.0
keyring==23.5.0
manhole==1.8.0
packaging==21.3
@@ -30,14 +30,15 @@ readme-renderer==34.0
requests==2.27.1
requests-toolbelt==0.9.1
rfc3986==2.0.0
+rich==12.1.0
SecretStorage==3.3.1
sip==6.5.1
six==1.16.0
toml==0.10.2
tomli==2.0.1
-tqdm==4.63.1
-twine==3.8.0
+twine==4.0.0
+typing_extensions==4.1.1
uritemplate==4.1.1
# urllib3==1.26.9
webencodings==0.5.1
-zipp==3.7.0
+zipp==3.8.0
diff --git a/misc/requirements/requirements-mypy.txt b/misc/requirements/requirements-mypy.txt
index d8fbba5ee..f3b1598a3 100644
--- a/misc/requirements/requirements-mypy.txt
+++ b/misc/requirements/requirements-mypy.txt
@@ -13,7 +13,6 @@ pluggy==1.0.0
Pygments==2.11.2
PyQt5-stubs==5.15.2.0
tomli==2.0.1
-types-dataclasses==0.6.4
types-PyYAML==6.0.5
typing_extensions==4.1.1
-zipp==3.7.0
+zipp==3.8.0
diff --git a/misc/requirements/requirements-mypy.txt-raw b/misc/requirements/requirements-mypy.txt-raw
index 4baeec11f..dd00d3219 100644
--- a/misc/requirements/requirements-mypy.txt-raw
+++ b/misc/requirements/requirements-mypy.txt-raw
@@ -3,7 +3,6 @@ lxml # For HTML reports
diff-cover
PyQt5-stubs
-types-dataclasses
types-PyYAML
# So stubs are available even on newer Python versions
diff --git a/misc/requirements/requirements-pylint.txt b/misc/requirements/requirements-pylint.txt
index 3e5ebea9e..8a79ff2fd 100644
--- a/misc/requirements/requirements-pylint.txt
+++ b/misc/requirements/requirements-pylint.txt
@@ -13,10 +13,10 @@ isort==5.10.1
lazy-object-proxy==1.7.1
mccabe==0.7.0
pefile==2021.9.3
-platformdirs==2.5.1 ; python_version>="3.7"
+platformdirs==2.5.1
pycparser==2.21
PyJWT==2.3.0
-pylint==2.13.3
+pylint==2.13.4
python-dateutil==2.8.2
./scripts/dev/pylint_checkers
requests==2.27.1
@@ -27,4 +27,3 @@ typing_extensions==4.1.1
uritemplate==4.1.1
# urllib3==1.26.9
wrapt==1.14.0
-platformdirs==2.4.0 ; python_version=="3.6.*"
diff --git a/misc/requirements/requirements-pylint.txt-raw b/misc/requirements/requirements-pylint.txt-raw
index 52633ec1a..54e12a02a 100644
--- a/misc/requirements/requirements-pylint.txt-raw
+++ b/misc/requirements/requirements-pylint.txt-raw
@@ -10,7 +10,3 @@ pefile
# Already included via test requirements
#@ ignore: urllib3
-
-# Python 3.6
-#@ markers: platformdirs python_version>="3.7"
-#@ add: platformdirs==2.4.0 ; python_version=="3.6.*"
diff --git a/misc/requirements/requirements-qutebrowser.txt-raw b/misc/requirements/requirements-qutebrowser.txt-raw
index b260fa16c..2025280fc 100644
--- a/misc/requirements/requirements-qutebrowser.txt-raw
+++ b/misc/requirements/requirements-qutebrowser.txt-raw
@@ -3,7 +3,6 @@ PyYAML
## stdlib backports
importlib-resources
-dataclasses
## Optional dependencies
Pygments # For :view-source --pygments or on QtWebKit
@@ -17,15 +16,3 @@ typing_extensions # from importlib-metadata
#@ markers: importlib-resources python_version=="3.7.*" or python_version=="3.8.*"
#@ markers: importlib-metadata python_version=="3.7.*"
#@ markers: typing_extensions python_version<"3.8"
-#@ markers: dataclasses python_version<"3.7"
-
-# Python 3.6
-#@ add: importlib-resources<5.6.0 ; python_version=="3.6.*"
-#@ add: importlib-metadata<4.9 ; python_version=="3.6.*"
-#
-#@ markers: zipp python_version>="3.7"
-#@ add: zipp<3.7 ; python_version=="3.6.*"
-#@ markers: MarkupSafe python_version>="3.7"
-#@ add: MarkupSafe<2.1.0 ; python_version=="3.6.*"
-#@ markers: Jinja2 python_version>="3.7"
-#@ add: Jinja2<3.1.0 ; python_version=="3.6.*"
diff --git a/misc/requirements/requirements-sphinx.txt b/misc/requirements/requirements-sphinx.txt
index bec429e04..a6f8cc262 100644
--- a/misc/requirements/requirements-sphinx.txt
+++ b/misc/requirements/requirements-sphinx.txt
@@ -24,4 +24,4 @@ sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
urllib3==1.26.9
-zipp==3.7.0
+zipp==3.8.0
diff --git a/misc/requirements/requirements-tests.txt b/misc/requirements/requirements-tests.txt
index 787d2791b..9fdb568ff 100644
--- a/misc/requirements/requirements-tests.txt
+++ b/misc/requirements/requirements-tests.txt
@@ -5,22 +5,22 @@ beautifulsoup4==4.10.0
certifi==2021.10.8
charset-normalizer==2.0.12
cheroot==8.6.0
-click==8.1.0 ; python_version>="3.7"
-coverage==6.3.2 ; python_version>="3.7"
+click==8.1.2
+coverage==6.3.2
execnet==1.9.0
-filelock==3.6.0 ; python_version>="3.7"
-Flask==2.1.0 ; python_version>="3.7"
+filelock==3.6.0
+Flask==2.1.1
glob2==0.7
hunter==3.4.3
-hypothesis==6.40.0 ; python_version>="3.7"
+hypothesis==6.41.0
icdiff==2.0.4
idna==3.3
-importlib-metadata==4.11.3 ; python_version=="3.7.*"
+importlib-metadata==4.11.3
iniconfig==1.1.1
-itsdangerous==2.1.2 ; python_version>="3.7"
-jaraco.functools==3.5.0 ; python_version>="3.7"
+itsdangerous==2.1.2
+jaraco.functools==3.5.0
# Jinja2==3.1.1
-Mako==1.2.0 ; python_version>="3.7"
+Mako==1.2.0
manhole==1.8.0
# MarkupSafe==2.1.1
more-itertools==8.12.0
@@ -33,14 +33,14 @@ py==1.11.0
py-cpuinfo==8.0.0
Pygments==2.11.2
pyparsing==3.0.7
-pytest==7.1.1 ; python_version>="3.7"
+pytest==7.1.1
pytest-bdd==4.1.0
pytest-benchmark==3.4.1
pytest-cov==3.0.0
pytest-forked==1.4.0
pytest-icdiff==0.5
pytest-instafail==0.4.2
-pytest-mock==3.7.0 ; python_version>="3.7"
+pytest-mock==3.7.0
pytest-qt==4.0.2
pytest-repeat==0.9.1
pytest-rerunfailures==10.2
@@ -52,25 +52,10 @@ requests-file==1.5.1
six==1.16.0
sortedcontainers==2.4.0
soupsieve==2.3.1
-tldextract==3.2.0 ; python_version>="3.7"
+tldextract==3.2.0
toml==0.10.2
-tomli==2.0.1 ; python_version>="3.7"
+tomli==2.0.1
urllib3==1.26.9
vulture==2.3
-Werkzeug==2.1.0 ; python_version>="3.7"
-zipp==3.7.0 ; python_version>="3.7"
-jaraco.functools<3.5 ; python_version=="3.6.*"
-tomli<2 ; python_version=="3.6.*"
-filelock==3.4.1 ; python_version=="3.6.*"
-hypothesis<6.32 ; python_version=="3.6.*"
-coverage<6.3 ; python_version=="3.6.*"
-pytest-mock<3.7 ; python_version=="3.6.*"
-itsdangerous<2.1.0 ; python_version=="3.6.*"
-tldextract<3.2.0 ; python_version=="3.6.*"
-Mako<1.2.0 ; python_version=="3.6.*"
-pytest<7.1.0 ; python_version=="3.6.*"
-click<8.1.0 ; python_version=="3.6.*"
-Flask<2.1.0 ; python_version=="3.6.*"
-Werkzeug<2.1.0 ; python_version=="3.6.*"
-zipp<3.7 ; python_version=="3.6.*"
-importlib-metadata<4.9 ; python_version=="3.6.*"
+Werkzeug==2.1.1
+zipp==3.8.0
diff --git a/misc/requirements/requirements-tests.txt-raw b/misc/requirements/requirements-tests.txt-raw
index 6338a1a97..5586a86ef 100644
--- a/misc/requirements/requirements-tests.txt-raw
+++ b/misc/requirements/requirements-tests.txt-raw
@@ -35,35 +35,3 @@ pytest-icdiff
tldextract
#@ ignore: Jinja2, MarkupSafe, colorama
-
-# Python 3.6
-#@ markers: jaraco.functools python_version>="3.7"
-#@ add: jaraco.functools<3.5 ; python_version=="3.6.*"
-#@ markers: tomli python_version>="3.7"
-#@ add: tomli<2 ; python_version=="3.6.*"
-#@ markers: filelock python_version>="3.7"
-#@ add: filelock==3.4.1 ; python_version=="3.6.*"
-#@ markers: hypothesis python_version>="3.7"
-#@ add: hypothesis<6.32 ; python_version=="3.6.*"
-#@ markers: coverage python_version>="3.7"
-#@ add: coverage<6.3 ; python_version=="3.6.*"
-#@ markers: pytest-mock python_version>="3.7"
-#@ add: pytest-mock<3.7 ; python_version=="3.6.*"
-#@ markers: itsdangerous python_version>="3.7"
-#@ add: itsdangerous<2.1.0 ; python_version=="3.6.*"
-#@ markers: tldextract python_version>="3.7"
-#@ add: tldextract<3.2.0 ; python_version=="3.6.*"
-#@ markers: Mako python_version>="3.7"
-#@ add: Mako<1.2.0 ; python_version=="3.6.*"
-#@ markers: pytest python_version>="3.7"
-#@ add: pytest<7.1.0 ; python_version=="3.6.*"
-#@ markers: click python_version>="3.7"
-#@ add: click<8.1.0 ; python_version=="3.6.*"
-#@ markers: Flask python_version>="3.7"
-#@ add: Flask<2.1.0 ; python_version=="3.6.*"
-#@ markers: Werkzeug python_version>="3.7"
-#@ add: Werkzeug<2.1.0 ; python_version=="3.6.*"
-#@ markers: zipp python_version>="3.7"
-#@ add: zipp<3.7 ; python_version=="3.6.*"
-#@ markers: importlib-metadata python_version=="3.7.*"
-#@ add: importlib-metadata<4.9 ; python_version=="3.6.*"
diff --git a/misc/requirements/requirements-tox.txt b/misc/requirements/requirements-tox.txt
index a87519740..45c0369a3 100644
--- a/misc/requirements/requirements-tox.txt
+++ b/misc/requirements/requirements-tox.txt
@@ -1,20 +1,16 @@
# This file is automatically generated by scripts/dev/recompile_requirements.py
distlib==0.3.4
-filelock==3.6.0 ; python_version>="3.7"
+filelock==3.6.0
packaging==21.3
-pip==22.0.4 ; python_version>="3.7"
-platformdirs==2.5.1 ; python_version>="3.7"
+pip==22.0.4
+platformdirs==2.5.1
pluggy==1.0.0
py==1.11.0
pyparsing==3.0.7
-setuptools==61.2.0 ; python_version>="3.7"
+setuptools==61.3.1
six==1.16.0
toml==0.10.2
tox==3.24.5
virtualenv==20.14.0
wheel==0.37.1
-setuptools<60 ; python_version=="3.6.*"
-filelock==3.4.1 ; python_version=="3.6.*"
-platformdirs==2.4.0 ; python_version=="3.6.*"
-pip==21.3.1 ; python_version=="3.6.*"
diff --git a/misc/requirements/requirements-tox.txt-raw b/misc/requirements/requirements-tox.txt-raw
index 2a9f30c5a..27d58e1f4 100644
--- a/misc/requirements/requirements-tox.txt-raw
+++ b/misc/requirements/requirements-tox.txt-raw
@@ -1,12 +1,2 @@
tox
wheel
-
-# Python 3.6
-#@ markers: setuptools python_version>="3.7"
-#@ add: setuptools<60 ; python_version=="3.6.*"
-#@ markers: filelock python_version>="3.7"
-#@ add: filelock==3.4.1 ; python_version=="3.6.*"
-#@ markers: platformdirs python_version>="3.7"
-#@ add: platformdirs==2.4.0 ; python_version=="3.6.*"
-#@ markers: pip python_version>="3.7"
-#@ add: pip==21.3.1 ; python_version=="3.6.*"
diff --git a/misc/userscripts/qute-bitwarden b/misc/userscripts/qute-bitwarden
index 30e7c6f2d..a44e08a14 100755
--- a/misc/userscripts/qute-bitwarden
+++ b/misc/userscripts/qute-bitwarden
@@ -103,7 +103,7 @@ def qute_command(command):
def ask_password(password_prompt_invocation):
process = subprocess.run(
shlex.split(password_prompt_invocation),
- universal_newlines=True,
+ text=True,
stdout=subprocess.PIPE,
)
if process.returncode > 0:
@@ -111,7 +111,7 @@ def ask_password(password_prompt_invocation):
master_pass = process.stdout.strip()
return subprocess.check_output(
['bw', 'unlock', '--raw', master_pass],
- universal_newlines=True,
+ text=True,
).strip()
@@ -122,7 +122,7 @@ def get_session_key(auto_lock, password_prompt_invocation):
else:
process = subprocess.run(
['keyctl', 'request', 'user', 'bw_session'],
- universal_newlines=True,
+ text=True,
stdout=subprocess.PIPE,
)
key_id = process.stdout.strip()
@@ -132,14 +132,14 @@ def get_session_key(auto_lock, password_prompt_invocation):
raise Exception('Could not unlock vault')
key_id = subprocess.check_output(
['keyctl', 'add', 'user', 'bw_session', session, '@u'],
- universal_newlines=True,
+ text=True,
).strip()
if auto_lock > 0:
subprocess.call(['keyctl', 'timeout', str(key_id), str(auto_lock)])
return subprocess.check_output(
['keyctl', 'pipe', str(key_id)],
- universal_newlines=True,
+ text=True,
).strip()
@@ -147,8 +147,7 @@ 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],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
+ capture_output=True,
)
err = process.stderr.decode(encoding).strip()
@@ -168,8 +167,7 @@ def get_totp_code(selection_id, domain_name, encoding, auto_lock, password_promp
session_key = get_session_key(auto_lock, password_prompt_invocation)
process = subprocess.run(
['bw', 'get', 'totp', '--session', session_key, selection_id],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
+ capture_output=True,
)
err = process.stderr.decode(encoding).strip()
diff --git a/misc/userscripts/qute-lastpass b/misc/userscripts/qute-lastpass
index edb48dfdc..e99a51a0f 100755
--- a/misc/userscripts/qute-lastpass
+++ b/misc/userscripts/qute-lastpass
@@ -86,7 +86,7 @@ def qute_command(command):
def pass_(domain, encoding):
domain = re.escape(domain)
args = ['lpass', 'show', '-x', '-j', '-G', '\\b{:s}'.format(domain)]
- process = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ process = subprocess.run(args, capture_output=True)
candidates = json.loads(process.stdout.decode(encoding).strip() or '[]')
err = process.stderr.decode(encoding).strip()
diff --git a/qutebrowser/browser/webkit/http.py b/qutebrowser/browser/webkit/http.py
index fed357e62..5a7cd8b34 100644
--- a/qutebrowser/browser/webkit/http.py
+++ b/qutebrowser/browser/webkit/http.py
@@ -91,6 +91,7 @@ class ContentDisposition:
except IndexError: # pragma: no cover
# WORKAROUND for https://bugs.python.org/issue37491
# Fixed in Python 3.7.5 and 3.8.0.
+ # Still getting failures on 3.10 on CI though
raise ContentDispositionError("Missing closing quote character")
except ValueError: # pragma: no cover
# WORKAROUND for https://bugs.python.org/issue42946
diff --git a/qutebrowser/completion/models/filepathcategory.py b/qutebrowser/completion/models/filepathcategory.py
index b7d74f57a..fd2cb58ce 100644
--- a/qutebrowser/completion/models/filepathcategory.py
+++ b/qutebrowser/completion/models/filepathcategory.py
@@ -65,7 +65,7 @@ class FilePathCategory(QAbstractListModel):
try:
return glob.glob(glob.escape(val) + '*')
except ValueError as e: # pragma: no cover
- # e.g. "embedded null byte" with \x00 on Python 3.6 and 3.7
+ # e.g. "embedded null byte" with \x00 on Python 3.7
log.completion.debug(f"Failed to glob: {e}")
return []
diff --git a/qutebrowser/components/braveadblock.py b/qutebrowser/components/braveadblock.py
index b1e5b8a29..977aa3ef2 100644
--- a/qutebrowser/components/braveadblock.py
+++ b/qutebrowser/components/braveadblock.py
@@ -175,11 +175,12 @@ class BraveAdBlocker:
hasattr(adblock, "__file__")):
proc = subprocess.run(
['pacman', '-Qo', adblock.__file__],
- stdout=subprocess.PIPE,
- universal_newlines=True,
+ capture_output=True,
+ text=True,
check=False,
)
logger.debug(proc.stdout)
+ logger.debug(proc.stderr)
raise
def _is_blocked(
diff --git a/qutebrowser/misc/checkpyver.py b/qutebrowser/misc/checkpyver.py
index e9a7a1eef..7d6a524c3 100644
--- a/qutebrowser/misc/checkpyver.py
+++ b/qutebrowser/misc/checkpyver.py
@@ -43,11 +43,11 @@ except ImportError: # pragma: no cover
# to stderr.
def check_python_version():
"""Check if correct python version is run."""
- if sys.hexversion < 0x03060100:
+ if sys.hexversion < 0x03070000:
# We don't use .format() and print_function here just in case someone
# still has < 2.6 installed.
version_str = '.'.join(map(str, sys.version_info[:3]))
- text = ("At least Python 3.6.1 is required to run qutebrowser, but " +
+ text = ("At least Python 3.7 is required to run qutebrowser, but " +
"it's running with " + version_str + ".\n")
if Tk and '--no-err-windows' not in sys.argv: # pragma: no cover
root = Tk()
diff --git a/qutebrowser/misc/earlyinit.py b/qutebrowser/misc/earlyinit.py
index 034d7ff74..4b3df4db2 100644
--- a/qutebrowser/misc/earlyinit.py
+++ b/qutebrowser/misc/earlyinit.py
@@ -19,7 +19,7 @@
"""Things which need to be done really early (e.g. before importing Qt).
-At this point we can be sure we have all python 3.6.1 features available.
+At this point we can be sure we have all python 3.7 features available.
"""
try:
@@ -235,7 +235,6 @@ def check_libraries():
modules = {
'jinja2': _missing_str("jinja2"),
'yaml': _missing_str("PyYAML"),
- 'dataclasses': _missing_str("dataclasses"),
'PyQt5.QtQml': _missing_str("PyQt5.QtQml"),
'PyQt5.QtSql': _missing_str("PyQt5.QtSql"),
'PyQt5.QtOpenGL': _missing_str("PyQt5.QtOpenGL"),
diff --git a/qutebrowser/utils/utils.py b/qutebrowser/utils/utils.py
index 9c68932f3..a28d662b3 100644
--- a/qutebrowser/utils/utils.py
+++ b/qutebrowser/utils/utils.py
@@ -784,30 +784,13 @@ def mimetype_extension(mimetype: str) -> Optional[str]:
This mostly delegates to Python's mimetypes.guess_extension(), but backports some
changes (via a simple override dict) which are missing from earlier Python versions.
- Most likely, this can be dropped once the minimum Python version is raised to 3.7.
+ Most likely, this can be dropped once the minimum Python version is raised to 3.10.
"""
overrides = {
+ # Added in 3.10
+ "application/x-hdf5": ".h5",
# Added around 3.8
"application/manifest+json": ".webmanifest",
- "application/x-hdf5": ".h5",
-
- # Added in Python 3.7
- "application/wasm": ".wasm",
-
- # Wrong values for Python 3.6
- # https://bugs.python.org/issue1043134
- # https://github.com/python/cpython/pull/14375
- "application/octet-stream": ".bin", # not .a
- "application/postscript": ".ps", # not .ai
- "application/vnd.ms-excel": ".xls", # not .xlb
- "application/vnd.ms-powerpoint": ".ppt", # not .pot
- "application/xml": ".xsl", # not .rdf
- "audio/mpeg": ".mp3", # not .mp2
- "image/jpeg": ".jpg", # not .jpe
- "image/tiff": ".tiff", # not .tif
- "text/html": ".html", # not .htm
- "text/plain": ".txt", # not .bat
- "video/mpeg": ".mpeg", # not .m1v
}
if mimetype in overrides:
return overrides[mimetype]
diff --git a/requirements.txt b/requirements.txt
index 25c1bd98f..c4c681886 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,17 +2,11 @@
adblock==0.5.2
colorama==0.4.4
-dataclasses==0.6 ; python_version<"3.7"
importlib-metadata==4.11.3 ; python_version=="3.7.*"
importlib-resources==5.6.0 ; python_version=="3.7.*" or python_version=="3.8.*"
-Jinja2==3.1.1 ; python_version>="3.7"
-MarkupSafe==2.1.1 ; python_version>="3.7"
+Jinja2==3.1.1
+MarkupSafe==2.1.1
Pygments==2.11.2
PyYAML==6.0
typing_extensions==4.1.1 ; python_version<"3.8"
-zipp==3.7.0 ; python_version>="3.7"
-importlib-resources<5.6.0 ; python_version=="3.6.*"
-importlib-metadata<4.9 ; python_version=="3.6.*"
-zipp<3.7 ; python_version=="3.6.*"
-MarkupSafe<2.1.0 ; python_version=="3.6.*"
-Jinja2<3.1.0 ; python_version=="3.6.*"
+zipp==3.8.0
diff --git a/scripts/dev/build_release.py b/scripts/dev/build_release.py
index 797b15e52..a4fbadf15 100755
--- a/scripts/dev/build_release.py
+++ b/scripts/dev/build_release.py
@@ -302,7 +302,9 @@ def build_mac(*, gh_token, debug):
for d in ['dist', 'build']:
shutil.rmtree(d, ignore_errors=True)
utils.print_title("Updating 3rdparty content")
- update_3rdparty.run(ace=False, pdfjs=True, fancy_dmg=False, gh_token=gh_token)
+ # FIXME:qt6 Use modern PDF.js version here
+ update_3rdparty.run(ace=False, pdfjs=True, legacy_pdfjs=True, fancy_dmg=False,
+ gh_token=gh_token)
utils.print_title("Building .app via pyinstaller")
call_tox('pyinstaller-64', '-r', debug=debug)
utils.print_title("Patching .app")
@@ -395,8 +397,9 @@ def _build_windows_single(*, x64, skip_packaging, debug):
def build_windows(*, gh_token, skip_packaging, only_32bit, only_64bit, debug):
"""Build windows executables/setups."""
utils.print_title("Updating 3rdparty content")
- update_3rdparty.run(nsis=True, ace=False, pdfjs=True, fancy_dmg=False,
- gh_token=gh_token)
+ # FIXME:qt6 Use modern PDF.js version here
+ update_3rdparty.run(nsis=True, ace=False, pdfjs=True, legacy_pdfjs=True,
+ fancy_dmg=False, gh_token=gh_token)
utils.print_title("Building Windows binaries")
diff --git a/scripts/dev/changelog_urls.json b/scripts/dev/changelog_urls.json
index 0de1d68d9..1047a3880 100644
--- a/scripts/dev/changelog_urls.json
+++ b/scripts/dev/changelog_urls.json
@@ -27,7 +27,6 @@
"hypothesis": "https://hypothesis.readthedocs.io/en/latest/changes.html",
"mypy": "https://mypy-lang.blogspot.com/",
"types-PyYAML": "https://github.com/python/typeshed/commits/master/stubs/PyYAML",
- "types-dataclasses": "https://github.com/python/typeshed/commits/master/stubs/dataclasses",
"pytest": "https://docs.pytest.org/en/latest/changelog.html",
"iniconfig": "https://github.com/RonnyPfannschmidt/iniconfig/blob/master/CHANGELOG",
"tox": "https://tox.readthedocs.io/en/latest/changelog.html",
@@ -140,7 +139,6 @@
"importlib-resources": "https://importlib-resources.readthedocs.io/en/latest/history.html",
"importlib-metadata": "https://github.com/python/importlib_metadata/blob/main/CHANGES.rst",
"zipp": "https://github.com/jaraco/zipp/blob/main/CHANGES.rst",
- "dataclasses": "https://github.com/ericvsmith/dataclasses#release-history",
"pip": "https://pip.pypa.io/en/stable/news/",
"wheel": "https://wheel.readthedocs.io/en/stable/news.html",
"setuptools": "https://setuptools.readthedocs.io/en/latest/history.html",
@@ -154,8 +152,9 @@
"readme-renderer": "https://github.com/pypa/readme_renderer/blob/main/CHANGES.rst",
"requests-toolbelt": "https://github.com/requests/toolbelt/blob/master/HISTORY.rst",
"rfc3986": "https://rfc3986.readthedocs.io/en/latest/release-notes/index.html",
- "tqdm": "https://tqdm.github.io/releases/",
"twine": "https://twine.readthedocs.io/en/stable/changelog.html",
"webencodings": "https://github.com/gsnedders/python-webencodings/commits/master",
- "PyJWT": "https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst"
+ "PyJWT": "https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst",
+ "commonmark": "https://github.com/readthedocs/commonmark.py/blob/master/CHANGELOG.md",
+ "rich": "https://github.com/Textualize/rich/blob/master/CHANGELOG.md"
}
diff --git a/scripts/dev/check_coverage.py b/scripts/dev/check_coverage.py
index c66cb3e8d..8f1d2df2b 100644
--- a/scripts/dev/check_coverage.py
+++ b/scripts/dev/check_coverage.py
@@ -333,7 +333,7 @@ def main_check():
subprocess.run([sys.executable, '-m', 'coverage', 'report',
'--show-missing', '--include', filters], check=True)
print()
- print("To debug this, run 'tox -e py36-pyqt515-cov' "
+ print("To debug this, run 'tox -e py39-pyqt515-cov' "
"(replace Python/Qt versions based on your system) locally and check "
"htmlcov/index.html")
print("or check https://codecov.io/github/qutebrowser/qutebrowser")
@@ -353,7 +353,7 @@ def main_check_all():
tests.
This runs pytest with the used executable, so check_coverage.py should be
- called with something like ./.tox/py36/bin/python.
+ called with something like ./.tox/py39/bin/python.
"""
for test_file, src_file in PERFECT_FILES:
if test_file is None:
diff --git a/scripts/dev/misc_checks.py b/scripts/dev/misc_checks.py
index 05fdb7932..908daad4d 100644
--- a/scripts/dev/misc_checks.py
+++ b/scripts/dev/misc_checks.py
@@ -50,7 +50,7 @@ def _get_files(
filenames = subprocess.run(
['git', 'ls-files', '--cached', '--others', '--exclude-standard', '-z'],
stdout=subprocess.PIPE,
- universal_newlines=True,
+ text=True,
check=True,
)
all_ignored = ignored or []
diff --git a/scripts/dev/recompile_requirements.py b/scripts/dev/recompile_requirements.py
index f8337b21f..365f9a51e 100644
--- a/scripts/dev/recompile_requirements.py
+++ b/scripts/dev/recompile_requirements.py
@@ -239,6 +239,9 @@ def extract_requirement_name(path: pathlib.Path) -> str:
e.g. "pylint" from "misc/requirements/requirements-pylint.txt"
"""
+ if path == pathlib.Path("requirements.txt"):
+ return "qutebrowser"
+
prefix = "requirements-"
assert path.suffix == ".txt", path
assert path.stem.startswith(prefix), path
@@ -419,7 +422,7 @@ def test_tox():
list_proc = subprocess.run([venv_python, '-m', 'tox', '--listenvs'],
check=True,
stdout=subprocess.PIPE,
- universal_newlines=True)
+ text=True)
environments = list_proc.stdout.strip().split('\n')
for env in environments:
with utils.gha_group('tox for {}'.format(env)):
diff --git a/scripts/dev/run_pylint_on_tests.py b/scripts/dev/run_pylint_on_tests.py
index a44828a85..28c6e32c9 100644
--- a/scripts/dev/run_pylint_on_tests.py
+++ b/scripts/dev/run_pylint_on_tests.py
@@ -64,9 +64,6 @@ def main():
'import-error',
# tests/helpers imports
'wrong-import-order',
- # https://github.com/PyCQA/pylint/issues/6036
- # https://github.com/PyCQA/pylint/issues/6037
- 'unnecessary-ellipsis',
]
toxinidir = sys.argv[1]
diff --git a/scripts/dev/update_3rdparty.py b/scripts/dev/update_3rdparty.py
index 60b72d110..b1991fa1f 100755
--- a/scripts/dev/update_3rdparty.py
+++ b/scripts/dev/update_3rdparty.py
@@ -64,7 +64,20 @@ def download_nsis_plugins():
urllib.request.urlcleanup()
-def get_latest_pdfjs_url(gh_token):
+def find_pdfjs_asset(assets, legacy):
+ """Find the PDF.js asset to use."""
+ for asset in assets:
+ name = asset["name"]
+ if (
+ name.startswith("pdfjs-") and
+ name.endswith("-dist.zip") and
+ name.endswith("-legacy-dist.zip") == legacy
+ ):
+ return asset
+ raise Exception(f"No pdfjs found in {assets}")
+
+
+def get_latest_pdfjs_url(gh_token, legacy):
"""Get the URL of the latest pdf.js prebuilt package.
Returns a (version, url)-tuple.
@@ -83,22 +96,25 @@ def get_latest_pdfjs_url(gh_token):
with urllib.request.urlopen(request) as fp:
data = json.loads(fp.read().decode('utf-8'))
- download_url = data['assets'][0]['browser_download_url']
+ asset = find_pdfjs_asset(data["assets"], legacy=legacy)
+
+ download_url = asset['browser_download_url']
version_name = data['name']
return (version_name, download_url)
-def update_pdfjs(target_version=None, gh_token=None):
+def update_pdfjs(target_version=None, legacy=False, gh_token=None):
"""Download and extract the latest pdf.js version.
If target_version is not None, download the given version instead.
Args:
target_version: None or version string ('x.y.z')
+ legacy: Whether to download the legacy build for 83-based.
gh_token: GitHub token to use for the API. Optional except on CI.
"""
if target_version is None:
- version, url = get_latest_pdfjs_url(gh_token)
+ version, url = get_latest_pdfjs_url(gh_token, legacy=legacy)
else:
# We need target_version as x.y.z, without the 'v' prefix, though the
# user might give it on the command line
@@ -107,13 +123,14 @@ def update_pdfjs(target_version=None, gh_token=None):
# version should have the prefix to be consistent with the return value
# of get_latest_pdfjs_url()
version = 'v' + target_version
+ suffix = "-legacy" if legacy else ""
url = ('https://github.com/mozilla/pdf.js/releases/download/'
- 'v{0}/pdfjs-{0}-dist.zip').format(target_version)
+ f'{version}/pdfjs-{target_version}{suffix}-dist.zip')
os.chdir(os.path.join(os.path.dirname(os.path.abspath(__file__)),
'..', '..'))
target_path = os.path.join('qutebrowser', '3rdparty', 'pdfjs')
- print("=> Downloading pdf.js {}".format(version))
+ print(f"=> Downloading pdf.js {version}{' (legacy)' if legacy else ''}")
try:
(archive_path, _headers) = urllib.request.urlretrieve(url)
except urllib.error.HTTPError as error:
@@ -167,13 +184,13 @@ def test_dicts():
print('ERROR: {}'.format(response.status))
-def run(nsis=False, ace=False, pdfjs=True, fancy_dmg=False, pdfjs_version=None,
- dicts=False, gh_token=None):
+def run(nsis=False, ace=False, pdfjs=True, legacy_pdfjs=False, fancy_dmg=False,
+ pdfjs_version=None, dicts=False, gh_token=None):
"""Update components based on the given arguments."""
if nsis:
download_nsis_plugins()
if pdfjs:
- update_pdfjs(pdfjs_version, gh_token=gh_token)
+ update_pdfjs(pdfjs_version, legacy=legacy_pdfjs, gh_token=gh_token)
if ace:
update_ace()
if fancy_dmg:
@@ -191,6 +208,9 @@ def main():
help='Specify pdfjs version. If not given, '
'the latest version is used.',
required=False, metavar='VERSION')
+ parser.add_argument("--legacy-pdfjs",
+ help="Use legacy PDF.js build (for 83-based)",
+ action='store_true')
parser.add_argument('--fancy-dmg', help="Update fancy-dmg Makefile",
action='store_true')
parser.add_argument(
@@ -202,7 +222,8 @@ def main():
'--gh-token', help="GitHub token to use.", nargs='?')
args = parser.parse_args()
run(nsis=False, ace=True, pdfjs=True, fancy_dmg=args.fancy_dmg,
- pdfjs_version=args.pdfjs, dicts=args.dicts, gh_token=args.gh_token)
+ pdfjs_version=args.pdfjs, legacy_pdfjs=args.legacy_pdfjs,
+ dicts=args.dicts, gh_token=args.gh_token)
if __name__ == '__main__':
diff --git a/scripts/link_pyqt.py b/scripts/link_pyqt.py
index 158cc145d..0ec7f2556 100644
--- a/scripts/link_pyqt.py
+++ b/scripts/link_pyqt.py
@@ -44,13 +44,13 @@ def run_py(executable, *code):
f.write('\n'.join(code))
cmd = [executable, filename]
try:
- ret = subprocess.run(cmd, universal_newlines=True, check=True,
+ ret = subprocess.run(cmd, text=True, check=True,
stdout=subprocess.PIPE).stdout
finally:
os.remove(filename)
else:
cmd = [executable, '-c', '\n'.join(code)]
- ret = subprocess.run(cmd, universal_newlines=True, check=True,
+ ret = subprocess.run(cmd, text=True, check=True,
stdout=subprocess.PIPE).stdout
return ret.rstrip()
diff --git a/scripts/mkvenv.py b/scripts/mkvenv.py
index 7f6920bb8..737ea145d 100755
--- a/scripts/mkvenv.py
+++ b/scripts/mkvenv.py
@@ -147,7 +147,7 @@ def run_venv(
return subprocess.run(
[str(venv_dir / subdir / executable)] + [str(arg) for arg in args],
check=True,
- universal_newlines=capture_output or capture_error,
+ text=capture_output or capture_error,
stdout=subprocess.PIPE if capture_output else None,
stderr=subprocess.PIPE if capture_error else None,
env=proc_env,
diff --git a/scripts/setupcommon.py b/scripts/setupcommon.py
index b1d246044..bd549d7cc 100644
--- a/scripts/setupcommon.py
+++ b/scripts/setupcommon.py
@@ -43,7 +43,7 @@ def _call_git(gitpath, *args):
return subprocess.run(
['git'] + list(args),
cwd=gitpath, check=True,
- stdout=subprocess.PIPE).stdout.decode('UTF-8').strip()
+ stdout=subprocess.PIPE, text=True).stdout.strip()
def _git_str():
diff --git a/setup.py b/setup.py
index 4c4bd3243..cb088e04c 100755
--- a/setup.py
+++ b/setup.py
@@ -72,9 +72,8 @@ try:
['qutebrowser = qutebrowser.qutebrowser:main']},
zip_safe=True,
install_requires=['jinja2', 'PyYAML',
- 'dataclasses; python_version < "3.7"',
'importlib_resources>=1.1.0; python_version < "3.9"'],
- python_requires='>=3.6',
+ python_requires='>=3.7',
name='qutebrowser',
version=_get_constant('version'),
description=_get_constant('description'),
@@ -96,7 +95,6 @@ try:
'Operating System :: MacOS',
'Operating System :: POSIX :: BSD',
'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
diff --git a/tests/end2end/test_invocations.py b/tests/end2end/test_invocations.py
index 43809cfd4..0d49ff109 100644
--- a/tests/end2end/test_invocations.py
+++ b/tests/end2end/test_invocations.py
@@ -336,7 +336,7 @@ def test_command_on_start(request, quteproc_new):
quteproc_new.wait_for_quit()
-@pytest.mark.parametrize('python', ['python2', 'python3.5'])
+@pytest.mark.parametrize('python', ['python2', 'python3.6'])
def test_launching_with_old_python(python):
try:
proc = subprocess.run(
@@ -346,7 +346,7 @@ def test_launching_with_old_python(python):
except FileNotFoundError:
pytest.skip(f"{python} not found")
assert proc.returncode == 1
- error = "At least Python 3.6.1 is required to run qutebrowser"
+ error = "At least Python 3.7 is required to run qutebrowser"
assert proc.stderr.decode('ascii').startswith(error)
diff --git a/tests/unit/config/test_configtypes.py b/tests/unit/config/test_configtypes.py
index ef3007f71..c34efce54 100644
--- a/tests/unit/config/test_configtypes.py
+++ b/tests/unit/config/test_configtypes.py
@@ -19,7 +19,6 @@
"""Tests for qutebrowser.config.configtypes."""
import re
-import sys
import json
import math
import warnings
@@ -1501,12 +1500,8 @@ class TestRegex:
pytest.param('(' * 500, id='too many parens'),
pytest.param(r'foo\Xbar', id='invalid escape X'),
pytest.param(r'foo\Cbar', id='invalid escape C'),
- pytest.param(r'[[]]', id='nested set', marks=pytest.mark.skipif(
- sys.hexversion < 0x03070000,
- reason="Warning was added in Python 3.7")),
- pytest.param(r'[a||b]', id='set operation', marks=pytest.mark.skipif(
- sys.hexversion < 0x03070000,
- reason="Warning was added in Python 3.7")),
+ pytest.param(r'[[]]', id='nested set'),
+ pytest.param(r'[a||b]', id='set operation'),
])
def test_to_py_invalid(self, klass, val):
with pytest.raises(configexc.ValidationError):
diff --git a/tests/unit/misc/test_checkpyver.py b/tests/unit/misc/test_checkpyver.py
index 52e022a44..35f8cfeec 100644
--- a/tests/unit/misc/test_checkpyver.py
+++ b/tests/unit/misc/test_checkpyver.py
@@ -28,19 +28,18 @@ import pytest
from qutebrowser.misc import checkpyver
-TEXT = (r"At least Python 3.6.1 is required to run qutebrowser, but it's "
+TEXT = (r"At least Python 3.7 is required to run qutebrowser, but it's "
r"running with \d+\.\d+\.\d+.")
@pytest.mark.not_frozen
-@pytest.mark.parametrize('python', ['python2', 'python3.5'])
+@pytest.mark.parametrize('python', ['python2', 'python3.6'])
def test_old_python(python):
"""Run checkpyver with old python versions."""
try:
proc = subprocess.run(
[python, checkpyver.__file__, '--no-err-windows'],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
+ capture_output=True,
check=False)
except FileNotFoundError:
pytest.skip(f"{python} not found")
diff --git a/tests/unit/misc/userscripts/test_qute_lastpass.py b/tests/unit/misc/userscripts/test_qute_lastpass.py
index 24272a048..ebd9a7591 100644
--- a/tests/unit/misc/userscripts/test_qute_lastpass.py
+++ b/tests/unit/misc/userscripts/test_qute_lastpass.py
@@ -122,7 +122,7 @@ class TestQuteLastPassComponents:
subprocess_mock.assert_called_once_with(
['lpass', 'show', '-x', '-j', '-G', '\\bexample\\.com'],
- stdout=ANY, stderr=ANY)
+ capture_output=True)
def test_pass_returns_candidates(self, subprocess_mock):
"""Test if pass_ returns expected lpass site entry."""
@@ -263,7 +263,7 @@ class TestQuteLastPassMain:
subprocess_mock.assert_has_calls([
call(['lpass', 'show', '-x', '-j', '-G', '\\bwww\\.example\\.com'],
- stdout=ANY, stderr=ANY),
+ capture_output=True),
call(['rofi', '-dmenu'],
input=b'12345 | www.example.com | https://www.example.com | fake@fake.com\n23456 | Sites/www.example.com | https://www.example.com | john.doe@fake.com',
stdout=ANY)
@@ -328,13 +328,13 @@ class TestQuteLastPassMain:
subprocess_mock.assert_has_calls([
call(['lpass', 'show', '-x', '-j', '-G', '\\bwww\\.example\\.com'],
- stdout=ANY, stderr=ANY),
+ capture_output=True),
call(['lpass', 'show', '-x', '-j', '-G', '\\bexample\\.com'],
- stdout=ANY, stderr=ANY),
+ capture_output=True),
call(['lpass', 'show', '-x', '-j', '-G', '\\bwwwexample'],
- stdout=ANY, stderr=ANY),
+ capture_output=True),
call(['lpass', 'show', '-x', '-j', '-G', '\\bexample'],
- stdout=ANY, stderr=ANY),
+ capture_output=True),
call(['rofi', '-dmenu'],
input=b'12345 | www.example.com | https://www.example.com | fake@fake.com\n23456 | Sites/www.example.com | https://www.example.com | john.doe@fake.com\n345 | example.com | https://example.com | joe.doe@fake.com\n456 | Sites/example.com | http://example.com | jane.doe@fake.com',
stdout=ANY)
diff --git a/tests/unit/utils/test_standarddir.py b/tests/unit/utils/test_standarddir.py
index f5d8204a4..0ca635ae2 100644
--- a/tests/unit/utils/test_standarddir.py
+++ b/tests/unit/utils/test_standarddir.py
@@ -498,7 +498,7 @@ def test_no_qapplication(qapp, tmpdir, monkeypatch):
monkeypatch.setenv('HOME', str(home_dir))
proc = subprocess.run([sys.executable, str(pyfile)] + sys.path,
- universal_newlines=True,
+ text=True,
check=True,
stdout=subprocess.PIPE)
sub_locations = json.loads(proc.stdout)
diff --git a/tests/unit/utils/test_utils.py b/tests/unit/utils/test_utils.py
index 330ef3b96..4620c2198 100644
--- a/tests/unit/utils/test_utils.py
+++ b/tests/unit/utils/test_utils.py
@@ -931,7 +931,7 @@ def test_parse_duration_hypothesis(duration):
@pytest.mark.parametrize('mimetype, extension', [
('application/pdf', '.pdf'), # handled by Python
- ('text/plain', '.txt'), # wrong in Python 3.6, overridden
+ ('text/plain', '.txt'), # was wrong in Python 3.6, handled now
('application/manifest+json', '.webmanifest'), # newer
('text/xul', '.xul'), # strict=False
('doesnot/exist', None),
diff --git a/tox.ini b/tox.ini
index 370adbc9e..0990b1b4a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -18,7 +18,6 @@ passenv = PYTHON DISPLAY XAUTHORITY HOME USERNAME USER CI XDG_* QUTE_* DOCKER QT
basepython =
py: {env:PYTHON:python3}
py3: {env:PYTHON:python3}
- py36: {env:PYTHON:python3.6}
py37: {env:PYTHON:python3.7}
py38: {env:PYTHON:python3.8}
py39: {env:PYTHON:python3.9}