diff options
47 files changed, 156 insertions, 238 deletions
@@ -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 @@ -1,5 +1,5 @@ [mypy] -python_version = 3.6 +python_version = 3.7 ### --strict warn_unused_configs = True @@ -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(): @@ -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), @@ -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} |