Skip to content

Commit

Permalink
Initial drop of Python 3.5
Browse files Browse the repository at this point in the history
See #4800
  • Loading branch information
The-Compiler committed Oct 26, 2020
1 parent c79eb71 commit 685a662
Show file tree
Hide file tree
Showing 28 changed files with 91 additions and 187 deletions.
6 changes: 4 additions & 2 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ exclude = .*,__pycache__,resources.py
# D413: Missing blank line after last section (not in pep257?)
# A003: Builtin name for class attribute (needed for overridden methods)
# W504: line break after binary operator
# FI15: __future__ import "generator_stop" missing
ignore =
B001,B008,B305,
E128,E226,E265,E501,E402,E266,E722,E731,
Expand All @@ -46,8 +47,9 @@ ignore =
P101,P102,P103,
D102,D103,D106,D107,D104,D105,D209,D211,D401,D402,D403,D412,D413,
A003,
W504
min-version = 3.4.0
W504,
FI15
min-version = 3.6.0
max-complexity = 12
per-file-ignores =
qutebrowser/api/hook.py : N801
Expand Down
5 changes: 0 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,6 @@ jobs:
fail-fast: false
matrix:
include:
### PyQt 5.7.1 (Python 3.5)
# - testenv: py35-pyqt57
# os: ubuntu-16.04
# python: 3.5
# experimental: true
### PyQt 5.9 (Python 3.6)
- testenv: py36-pyqt59
os: ubuntu-18.04
Expand Down
2 changes: 0 additions & 2 deletions .mypy.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
[mypy]
# We also need to support 3.5, but if we'd chose that here, we'd need to deal
# with conditional imports (like secrets.py).
python_version = 3.6

# --strict
Expand Down
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
dist: xenial
language: python
python: 3.5
python: 3.6
os: linux
env: TESTENV=py35-pyqt57
env: TESTENV=py36-pyqt57

install:
- python -m pip install -U pip
Expand Down
3 changes: 1 addition & 2 deletions README.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,7 @@ Requirements

The following software and libraries are required to run qutebrowser:

* https://www.python.org/[Python] 3.5.2 or newer (3.6 - 3.8 recommended;
support for 3.5 will be dropped with qutebrowser v2.0.0)
* https://www.python.org/[Python] 3.6 or newer
* https://www.qt.io/[Qt] 5.7.1 or newer (5.14 recommended; support for < 5.11
will be dropped with qutebrowser v2.0.0) with the following modules:
- QtCore / qtbase
Expand Down
8 changes: 8 additions & 0 deletions doc/changelog.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ breaking changes (such as renamed commands) can happen in minor releases.
v2.0.0 (unreleased)
-------------------

Major changes
~~~~~~~~~~~~~

- At least Python 3.6 is now required to run qutebrowser, support for Python
3.5 is dropped. Note that Python 3.5 is
https://www.python.org/downloads/release/python-3510/[no longer supported
upstream] since September 2020.
Changed
~~~~~~~

Expand Down
2 changes: 1 addition & 1 deletion doc/contributing.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ unittests and several linters/checkers.
Currently, the following tox environments are available:

* Tests using https://www.pytest.org[pytest]:
- `py35`, `py36`: Run pytest for python 3.5/3.6 with the system-wide PyQt.
- `py36`, `py37`, ...: Run pytest for python 3.6/3.7/... with the system-wide PyQt.
- `py36-pyqt57`, ..., `py36-pyqt59`: Run pytest with the given PyQt version (`py35-*` also works).
- `py36-pyqt59-cov`: Run with coverage support (other Python/PyQt versions work too).
* `flake8`: Run various linting checks via https://pypi.python.org/pypi/flake8[flake8].
Expand Down
24 changes: 12 additions & 12 deletions doc/install.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,17 @@ Ubuntu 16.04 LTS / Linux Mint 18
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Ubuntu 16.04 doesn't come with an up-to-date engine (a new enough QtWebKit, or
QtWebEngine). However, it comes with Python 3.5, so you can
<<tox,install qutebrowser in a virtualenv>>.
QtWebEngine). It also comes with Python 3.5 which is not supported anymore since
qutebrowser v2.0.0.

You'll need some basic libraries to use the virtualenv-installed PyQt:
You should be able to install a newer Python (3.6+) 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
got this setup to work successfully, please submit a pull request to adjust these
instructions!

Note you'll need some basic libraries to use the virtualenv-installed PyQt:

----
# apt install --no-install-recommends git ca-certificates python3 python3-venv asciidoc libglib2.0-0 libgl1 libfontconfig1 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxcb-xfixes0 libxcb-xinerama0 libxcb-xkb1 libxkbcommon-x11-0 libdbus-1-3 libyaml-dev gcc python3-dev
Expand All @@ -44,12 +51,6 @@ You'll need some basic libraries to use the virtualenv-installed PyQt:
// FIXME not needed anymore?
// libxi6 libxrender1 libegl1-mesa

NOTE: Support for Python 3.5 will be dropped with the qutebrowser v2.0.0
release, preliminarily planned for late 2020. At that point, you will need to
either upgrade to a newer Ubuntu release, or use something like the
https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa[deadsnakes PPA] or
https://github.com/pyenv/pyenv[pyenv] to install a newer Python.

Debian Stretch
~~~~~~~~~~~~~~

Expand Down Expand Up @@ -439,9 +440,8 @@ 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.5 or newer, otherwise you'll get a "No
matching distribution found" error. Note that qutebrowser itself also requires
this.
- Make sure your `python3` is Python 3.6 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.
- It comes with a QtWebEngine compiled without proprietary codec support (such
Expand Down
15 changes: 6 additions & 9 deletions misc/requirements/requirements-tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ filelock==3.0.12
Flask==1.1.2
glob2==0.7
hunter==3.3.1
hypothesis==5.38.0 ; python_version>="3.6"
icdiff==1.9.1 ; python_version>="3.6"
hypothesis==5.38.0
icdiff==1.9.1
idna==2.10
iniconfig==1.1.1
itsdangerous==1.1.0
jaraco.functools==3.0.1 ; python_version>="3.6"
jaraco.functools==3.0.1
# Jinja2==2.11.2
Mako==1.1.3
manhole==1.6.0
Expand All @@ -30,7 +30,7 @@ packaging==20.4
parse==1.18.0
parse-type==0.5.2
pluggy==0.13.1
pprintpp==0.4.0 ; python_version>="3.6"
pprintpp==0.4.0
py==1.9.0
py-cpuinfo==7.0.0
Pygments==2.7.2
Expand All @@ -41,7 +41,7 @@ pytest-benchmark==3.2.3
pytest-clarity==0.3.0a0
pytest-cov==2.10.1
pytest-forked==1.3.0
pytest-icdiff==0.5 ; python_version>="3.6"
pytest-icdiff==0.5
pytest-instafail==0.4.2
pytest-mock==3.3.1
pytest-qt==3.3.0
Expand All @@ -59,8 +59,5 @@ termcolor==1.1.0
tldextract==3.0.2
toml==0.10.1
urllib3==1.25.11
vulture==2.1 ; python_version>="3.6"
vulture==2.1
Werkzeug==1.0.1
jaraco.functools==2.0; python_version<"3.6"
vulture==1.6; python_version<"3.6"
hypothesis<5.34.0; python_version<"3.6"
13 changes: 0 additions & 13 deletions misc/requirements/requirements-tests.txt-raw
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,4 @@ pytest-clarity
# Needed to test misc/userscripts/qute-lastpass
tldextract

#@ markers: pytest-icdiff python_version>="3.6"
#@ markers: icdiff python_version>="3.6"
#@ markers: pprintpp python_version>="3.6"

#@ markers: jaraco.functools python_version>="3.6"
#@ add: jaraco.functools==2.0; python_version<"3.6"

#@ markers: vulture python_version>="3.6"
#@ add: vulture==1.6; python_version<"3.6"

#@ markers: hypothesis python_version>="3.6"
#@ add: hypothesis<5.34.0; python_version<"3.6"

#@ ignore: Jinja2, MarkupSafe, colorama
7 changes: 4 additions & 3 deletions qutebrowser/browser/browsertab.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,14 +465,15 @@ class AbstractCaret(QObject):
follow_selected_done = pyqtSignal()

def __init__(self,
tab: 'AbstractTab',
mode_manager: modeman.ModeManager,
parent: QWidget = None) -> None:
super().__init__(parent)
self._widget = typing.cast(QWidget, None)
self._mode_manager = mode_manager
mode_manager.entered.connect(self._on_mode_entered)
mode_manager.left.connect(self._on_mode_left)
# self._tab is set by subclasses so mypy knows its concrete type.
self._tab = tab

def _on_mode_entered(self, mode: usertypes.KeyMode) -> None:
raise NotImplementedError
Expand Down Expand Up @@ -715,9 +716,9 @@ class AbstractElements:
[typing.Optional['webelem.AbstractWebElement']], None]
_ErrorCallback = typing.Callable[[Exception], None]

def __init__(self) -> None:
def __init__(self, tab: 'AbstractTab') -> None:
self._widget = typing.cast(QWidget, None)
# self._tab is set by subclasses so mypy knows its concrete type.
self._tab = tab

def find_css(self, selector: str,
callback: _MultiCallback,
Expand Down
15 changes: 2 additions & 13 deletions qutebrowser/browser/qutescheme.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,10 @@
import textwrap
import urllib
import collections
import base64
import typing
import secrets
from typing import TypeVar, Callable, Union, Tuple

try:
import secrets
except ImportError:
# New in Python 3.6
secrets = None # type: ignore[assignment]

from PyQt5.QtCore import QUrlQuery, QUrl, qVersion

import qutebrowser
Expand Down Expand Up @@ -449,12 +443,7 @@ def qute_settings(url: QUrl) -> _HandlerRet:
# Requests to qute://settings/set should only be allowed from
# qute://settings. As an additional security precaution, we generate a CSRF
# token to use here.
if secrets:
csrf_token = secrets.token_urlsafe()
else:
# On Python < 3.6, from secrets.py
token = base64.urlsafe_b64encode(os.urandom(32))
csrf_token = token.rstrip(b'=').decode('ascii')
csrf_token = secrets.token_urlsafe()

src = jinja.render('settings.html', title='settings',
configdata=configdata,
Expand Down
12 changes: 2 additions & 10 deletions qutebrowser/browser/webengine/webenginetab.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
from qutebrowser.misc import miscwidgets, objects, quitter
from qutebrowser.utils import (usertypes, qtutils, log, javascript, utils,
message, objreg, jinja, debug)
from qutebrowser.keyinput import modeman
from qutebrowser.qt import sip


Expand Down Expand Up @@ -356,12 +355,7 @@ class WebEngineCaret(browsertab.AbstractCaret):

"""QtWebEngine implementations related to moving the cursor/selection."""

def __init__(self,
tab: 'WebEngineTab',
mode_manager: modeman.ModeManager,
parent: QWidget = None) -> None:
super().__init__(mode_manager, parent)
self._tab = tab
_tab: 'WebEngineTab'

def _flags(self):
"""Get flags to pass to JS."""
Expand Down Expand Up @@ -786,9 +780,7 @@ class WebEngineElements(browsertab.AbstractElements):

"""QtWebEngine implemementations related to elements on the page."""

def __init__(self, tab: 'WebEngineTab') -> None:
super().__init__()
self._tab = tab
_tab: 'WebEngineTab'

def _js_cb_multiple(self, callback, error_cb, js_elems):
"""Handle found elements coming from JS and call the real callback.
Expand Down
5 changes: 1 addition & 4 deletions qutebrowser/browser/webkit/mhtml.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,7 @@ def _get_css_imports_cssutils(data, inline=False):
"""
try:
import cssutils
except (ImportError, re.error):
# Catching re.error because cssutils in earlier releases (<= 1.0) is
# broken on Python 3.5
# See https://bitbucket.org/cthedot/cssutils/issues/52
except ImportError:
return None

# We don't care about invalid CSS data, this will only litter the log
Expand Down
7 changes: 2 additions & 5 deletions qutebrowser/browser/webkit/webkittab.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,7 @@ def __init__(self,
tab: 'WebKitTab',
mode_manager: modeman.ModeManager,
parent: QWidget = None) -> None:
super().__init__(mode_manager, parent)
self._tab = tab
super().__init__(tab, mode_manager, parent)
self._selection_state = browsertab.SelectionState.none

@pyqtSlot(usertypes.KeyMode)
Expand Down Expand Up @@ -693,9 +692,7 @@ class WebKitElements(browsertab.AbstractElements):

"""QtWebKit implemementations related to elements on the page."""

def __init__(self, tab: 'WebKitTab') -> None:
super().__init__()
self._tab = tab
_tab: 'WebKitTab'

def find_css(self, selector, callback, error_cb, *, only_visible=False):
utils.unused(error_cb)
Expand Down
23 changes: 10 additions & 13 deletions qutebrowser/commands/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,22 +406,19 @@ def _get_param_value(self, param):
raise TypeError("{}: Legacy tuple type annotation!".format(
self.name))

if hasattr(typing, 'UnionMeta'):
# Python 3.5.2
# pylint: disable=no-member,useless-suppression
is_union = isinstance(
typ, typing.UnionMeta) # type: ignore[attr-defined]
else:
is_union = getattr(typ, '__origin__', None) is typing.Union
try:
origin = typing.get_origin(typ) # type: ignore[attr-defined]
except AttributeError:
# typing.get_origin was added in Python 3.8
origin = getattr(typ, '__origin__', None)

if is_union:
# this is... slightly evil, I know
if origin is typing.Union:
try:
types = list(typ.__args__)
types = list(typing.get_args(typ)) # type: ignore[attr-defined]
except AttributeError:
# Python 3.5.2
types = list(typ.__union_params__)
# pylint: enable=no-member,useless-suppression
# typing.get_args was added in Python 3.8
types = list(typ.__args__)

if param.default is not inspect.Parameter.empty:
types.append(type(param.default))
choices = self.get_arg_info(param).choices
Expand Down
Loading

0 comments on commit 685a662

Please sign in to comment.