From 505321c336408073655e33dd43f90dd327521351 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 18 Sep 2017 09:41:12 +0200 Subject: [PATCH] Drop support for Python 3.4 See #2742 --- README.asciidoc | 4 +- doc/changelog.asciidoc | 2 +- doc/contributing.asciidoc | 12 ++--- doc/install.asciidoc | 4 +- qutebrowser/browser/commands.py | 5 +- qutebrowser/browser/navigate.py | 2 +- qutebrowser/browser/shared.py | 2 +- qutebrowser/browser/webelem.py | 2 +- qutebrowser/commands/command.py | 8 ++- qutebrowser/config/config.py | 8 +-- qutebrowser/config/configexc.py | 3 +- qutebrowser/config/configfiles.py | 7 ++- qutebrowser/config/configtypes.py | 7 +-- qutebrowser/mainwindow/mainwindow.py | 8 ++- qutebrowser/mainwindow/tabbedbrowser.py | 3 +- qutebrowser/misc/checkpyver.py | 4 +- qutebrowser/misc/earlyinit.py | 2 +- qutebrowser/misc/sessions.py | 2 +- qutebrowser/utils/typing.py | 68 ------------------------- qutebrowser/utils/utils.py | 15 +++--- scripts/dev/check_coverage.py | 4 +- scripts/dev/ci/travis_backtrace.sh | 4 -- scripts/setupcommon.py | 3 +- tests/end2end/test_invocations.py | 2 +- tests/unit/commands/test_cmdutils.py | 3 +- tests/unit/misc/test_checkpyver.py | 6 +-- tests/unit/utils/test_typing.py | 54 -------------------- 27 files changed, 55 insertions(+), 189 deletions(-) delete mode 100644 qutebrowser/utils/typing.py delete mode 100644 tests/unit/utils/test_typing.py diff --git a/README.asciidoc b/README.asciidoc index 1f8de414d..652ea71b3 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -99,9 +99,7 @@ Requirements The following software and libraries are required to run qutebrowser: -* http://www.python.org/[Python] 3.4 or newer (3.6 recommended) - note that - support for Python 3.4 - https://github.com/qutebrowser/qutebrowser/issues/2742[will be dropped soon]. +* http://www.python.org/[Python] 3.5 or newer (3.6 recommended) * http://qt.io/[Qt] 5.7.1 or newer with the following modules: - QtCore / qtbase - QtQuick (part of qtbase in some distributions) diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index 48226e2e9..cdbdff015 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -22,7 +22,7 @@ Breaking changes - (TODO) Support for legacy QtWebKit (before 5.212 which is distributed independently from Qt) is dropped. -- (TODO) Support for Python 3.4 is dropped. +- Support for Python 3.4 is dropped. - Support for Qt before 5.7.1 and PyQt before 5.7 is dropped. - (TODO) New dependency on ruamel.yaml; dropped PyYAML dependency. - (TODO) The QtWebEngine backend is now used by default if available. diff --git a/doc/contributing.asciidoc b/doc/contributing.asciidoc index 4b02c4c12..1b2f4be4e 100644 --- a/doc/contributing.asciidoc +++ b/doc/contributing.asciidoc @@ -180,7 +180,7 @@ In the _scripts/_ subfolder there's a `run_profile.py` which profiles the code and shows a graphical representation of what takes how much time. It uses the built-in Python -https://docs.python.org/3.4/library/profile.html[cProfile] module and can show +https://docs.python.org/3.6/library/profile.html[cProfile] module and can show the output in four different ways: * Raw profile file (`--profile-tool=none`) @@ -535,11 +535,11 @@ ____ Setting up a Windows Development Environment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* Install https://www.python.org/downloads/release/python-344/[Python 3.4] -* Install https://sourceforge.net/projects/pyqt/files/PyQt5/PyQt-5.5.1/[PyQt 5.5] -* Create a file at `C:\Windows\system32\python3.bat` with the following content: - `@C:\Python34\python %*` - This will make the Python 3.4 interpreter available as `python3`, which is used by various development scripts. +* Install https://www.python.org/downloads/release/python-362/[Python 3.6]. +* 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/install.asciidoc b/doc/install.asciidoc index 5af011645..4564a8dde 100644 --- a/doc/install.asciidoc +++ b/doc/install.asciidoc @@ -17,8 +17,8 @@ running. Debian Jessie / Ubuntu 14.04 LTS / Linux Mint < 18 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Those distributions only have Python 3.4 and a too old Qt version available. A -newer Qt isn't easily installable on Python 3.4, unfortunately. +Those distributions only have Python 3.4 and a too old Qt version available, +while qutebrowser requires Python 3.5 and Qt 5.7.1 or newer. It should be possible to install Python 3.5 e.g. from the https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa[deadsnakes PPA] or via_ipca diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 79a8502cd..5bb07f129 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -24,6 +24,7 @@ import sys import os.path import shlex import functools +import typing from PyQt5.QtWidgets import QApplication, QTabBar, QDialog from PyQt5.QtCore import Qt, QUrl, QEvent, QUrlQuery @@ -39,10 +40,11 @@ from qutebrowser.browser import (urlmarks, browsertab, inspector, navigate, webelem, downloads) from qutebrowser.keyinput import modeman from qutebrowser.utils import (message, usertypes, log, qtutils, urlutils, - objreg, utils, typing, debug) + objreg, utils, debug) from qutebrowser.utils.usertypes import KeyMode from qutebrowser.misc import editor, guiprocess from qutebrowser.completion.models import urlmodel, miscmodels +from qutebrowser.mainwindow import mainwindow class CommandDispatcher: @@ -70,7 +72,6 @@ class CommandDispatcher: def _new_tabbed_browser(self, private): """Get a tabbed-browser from a new window.""" - from qutebrowser.mainwindow import mainwindow new_window = mainwindow.MainWindow(private=private) new_window.show() return new_window.tabbed_browser diff --git a/qutebrowser/browser/navigate.py b/qutebrowser/browser/navigate.py index dcb578072..2278a2fa7 100644 --- a/qutebrowser/browser/navigate.py +++ b/qutebrowser/browser/navigate.py @@ -24,6 +24,7 @@ import posixpath from qutebrowser.browser import webelem from qutebrowser.config import config from qutebrowser.utils import objreg, urlutils, log, message, qtutils +from qutebrowser.mainwindow import mainwindow class Error(Exception): @@ -134,7 +135,6 @@ def prevnext(*, browsertab, win_id, baseurl, prev=False, window=win_id) if window: - from qutebrowser.mainwindow import mainwindow new_window = mainwindow.MainWindow( private=cur_tabbed_browser.private) new_window.show() diff --git a/qutebrowser/browser/shared.py b/qutebrowser/browser/shared.py index cfa1e98da..ab1b6ad9f 100644 --- a/qutebrowser/browser/shared.py +++ b/qutebrowser/browser/shared.py @@ -23,6 +23,7 @@ import html from qutebrowser.config import config from qutebrowser.utils import usertypes, message, log, objreg, jinja +from qutebrowser.mainwindow import mainwindow class CallSuper(Exception): @@ -234,7 +235,6 @@ def get_tab(win_id, target): elif target == usertypes.ClickTarget.window: tabbed_browser = objreg.get('tabbed-browser', scope='window', window=win_id) - from qutebrowser.mainwindow import mainwindow window = mainwindow.MainWindow(private=tabbed_browser.private) window.show() win_id = window.win_id diff --git a/qutebrowser/browser/webelem.py b/qutebrowser/browser/webelem.py index df3001b52..85efebd03 100644 --- a/qutebrowser/browser/webelem.py +++ b/qutebrowser/browser/webelem.py @@ -31,6 +31,7 @@ from PyQt5.QtGui import QMouseEvent from qutebrowser.config import config from qutebrowser.keyinput import modeman +from qutebrowser.mainwindow import mainwindow from qutebrowser.utils import log, usertypes, utils, qtutils, objreg @@ -372,7 +373,6 @@ class AbstractWebElement(collections.abc.MutableMapping): background = click_target == usertypes.ClickTarget.tab_bg tabbed_browser.tabopen(url, background=background) elif click_target == usertypes.ClickTarget.window: - from qutebrowser.mainwindow import mainwindow window = mainwindow.MainWindow(private=tabbed_browser.private) window.show() window.tabbed_browser.tabopen(url) diff --git a/qutebrowser/commands/command.py b/qutebrowser/commands/command.py index 148be8393..233f9d1a7 100644 --- a/qutebrowser/commands/command.py +++ b/qutebrowser/commands/command.py @@ -22,10 +22,11 @@ import inspect import collections import traceback +import typing from qutebrowser.commands import cmdexc, argparser from qutebrowser.utils import (log, utils, message, docutils, objreg, - usertypes, typing) + usertypes) from qutebrowser.utils import debug as debug_utils from qutebrowser.misc import objects @@ -415,10 +416,7 @@ class Command: # We also can't use isinstance here because typing.Union doesn't # support that. # pylint: disable=no-member,useless-suppression - try: - types = list(typ.__union_params__) - except AttributeError: - types = list(typ.__args__) + types = list(typ.__args__) # pylint: enable=no-member,useless-suppression if param.default is not inspect.Parameter.empty: types.append(type(param.default)) diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py index 4ccadfefb..ff954486b 100644 --- a/qutebrowser/config/config.py +++ b/qutebrowser/config/config.py @@ -28,9 +28,9 @@ from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QUrl from PyQt5.QtWidgets import QMessageBox from qutebrowser.config import configdata, configexc, configtypes, configfiles -from qutebrowser.utils import utils, objreg, message, log, usertypes +from qutebrowser.utils import utils, objreg, message, log, usertypes, jinja from qutebrowser.misc import objects, msgbox -from qutebrowser.commands import cmdexc, cmdutils +from qutebrowser.commands import cmdexc, cmdutils, runners from qutebrowser.completion.models import configmodel # An easy way to access the config from other code via config.val.foo @@ -176,8 +176,6 @@ class KeyConfig: def bind(self, key, command, *, mode, force=False, save_yaml=False): """Add a new binding from key to command.""" - # Doing this here to work around a Python 3.4 circular import - from qutebrowser.commands import runners key = self._prepare(key, mode) parser = runners.CommandParser() @@ -594,8 +592,6 @@ def set_register_stylesheet(obj, *, stylesheet=None, update=True): @functools.lru_cache() def _render_stylesheet(stylesheet): """Render the given stylesheet jinja template.""" - # Imported here to avoid a Python 3.4 circular import - from qutebrowser.utils import jinja with jinja.environment.no_autoescape(): template = jinja.environment.from_string(stylesheet) return template.render(conf=val) diff --git a/qutebrowser/config/configexc.py b/qutebrowser/config/configexc.py index dd0da5401..a4514cd1f 100644 --- a/qutebrowser/config/configexc.py +++ b/qutebrowser/config/configexc.py @@ -19,7 +19,7 @@ """Exceptions related to config parsing.""" -from qutebrowser.utils import utils +from qutebrowser.utils import utils, jinja class Error(Exception): @@ -108,7 +108,6 @@ class ConfigFileErrors(Error): def to_html(self): """Get the error texts as a HTML snippet.""" - from qutebrowser.utils import jinja template = jinja.environment.from_string(""" Errors occurred while reading {{ basename }}: diff --git a/qutebrowser/config/configfiles.py b/qutebrowser/config/configfiles.py index 093ad4aee..0ca688faa 100644 --- a/qutebrowser/config/configfiles.py +++ b/qutebrowser/config/configfiles.py @@ -30,7 +30,7 @@ import yaml from PyQt5.QtCore import QSettings import qutebrowser -from qutebrowser.config import configexc +from qutebrowser.config import configexc, config from qutebrowser.utils import standarddir, utils, qtutils @@ -152,8 +152,8 @@ class ConfigAPI: errors: Errors which occurred while setting options. """ - def __init__(self, config, keyconfig): - self._config = config + def __init__(self, conf, keyconfig): + self._config = conf self._keyconfig = keyconfig self.load_autoconfig = True self.errors = [] @@ -189,7 +189,6 @@ class ConfigAPI: def read_config_py(filename=None): """Read a config.py file.""" - from qutebrowser.config import config api = ConfigAPI(config.instance, config.key_instance) if filename is None: diff --git a/qutebrowser/config/configtypes.py b/qutebrowser/config/configtypes.py index b8c9c1e05..b92722d16 100644 --- a/qutebrowser/config/configtypes.py +++ b/qutebrowser/config/configtypes.py @@ -59,9 +59,9 @@ from PyQt5.QtCore import QUrl, Qt from PyQt5.QtGui import QColor, QFont from PyQt5.QtWidgets import QTabWidget, QTabBar -from qutebrowser.commands import cmdutils +from qutebrowser.commands import cmdutils, runners, cmdexc from qutebrowser.config import configexc -from qutebrowser.utils import standarddir, utils, qtutils +from qutebrowser.utils import standarddir, utils, qtutils, urlutils SYSTEM_PROXY = object() # Return value for Proxy type @@ -791,7 +791,6 @@ class Command(BaseType): if not Command.unvalidated: Command.unvalidated = True try: - from qutebrowser.commands import runners, cmdexc parser = runners.CommandParser() try: parser.parse_all(value) @@ -1287,7 +1286,6 @@ class Proxy(BaseType): ('none', "Don't use any proxy")) def to_py(self, value): - from qutebrowser.utils import urlutils self._basic_py_validation(value, str) if not value: return None @@ -1352,7 +1350,6 @@ class FuzzyUrl(BaseType): """A URL which gets interpreted as search if needed.""" def to_py(self, value): - from qutebrowser.utils import urlutils self._basic_py_validation(value, str) if not value: return None diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index 04ae464b3..373a9030a 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -31,8 +31,7 @@ from qutebrowser.commands import runners, cmdutils from qutebrowser.config import config, configfiles from qutebrowser.utils import (message, log, usertypes, qtutils, objreg, utils, jinja, debug) -from qutebrowser.mainwindow import tabbedbrowser, messageview, prompt -from qutebrowser.mainwindow.statusbar import bar +from qutebrowser.mainwindow import messageview, prompt from qutebrowser.completion import completionwidget, completer from qutebrowser.keyinput import modeman from qutebrowser.browser import (commands, downloadview, hints, @@ -140,6 +139,11 @@ class MainWindow(QWidget): parent: The parent the window should get. """ super().__init__(parent) + # Late import to avoid a circular dependency + # - browsertab -> hints -> webelem -> mainwindow -> bar -> browsertab + from qutebrowser.mainwindow import tabbedbrowser + from qutebrowser.mainwindow.statusbar import bar + self.setAttribute(Qt.WA_DeleteOnClose) self._commandrunner = None self._overlays = [] diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py index 5c46ec481..acf966cd5 100644 --- a/qutebrowser/mainwindow/tabbedbrowser.py +++ b/qutebrowser/mainwindow/tabbedbrowser.py @@ -28,7 +28,7 @@ from PyQt5.QtGui import QIcon from qutebrowser.config import config from qutebrowser.keyinput import modeman -from qutebrowser.mainwindow import tabwidget +from qutebrowser.mainwindow import tabwidget, mainwindow from qutebrowser.browser import signalfilter, browsertab from qutebrowser.utils import (log, usertypes, utils, qtutils, objreg, urlutils, message, jinja) @@ -432,7 +432,6 @@ class TabbedBrowser(tabwidget.TabWidget): if (config.val.tabs.tabs_are_windows and self.count() > 0 and not ignore_tabs_are_windows): - from qutebrowser.mainwindow import mainwindow window = mainwindow.MainWindow(private=self.private) window.show() tabbed_browser = objreg.get('tabbed-browser', scope='window', diff --git a/qutebrowser/misc/checkpyver.py b/qutebrowser/misc/checkpyver.py index 34183041b..fc3dde673 100644 --- a/qutebrowser/misc/checkpyver.py +++ b/qutebrowser/misc/checkpyver.py @@ -43,12 +43,12 @@ except ImportError: # pragma: no cover # to stderr. def check_python_version(): """Check if correct python version is run.""" - if sys.hexversion < 0x03040000: + if sys.hexversion < 0x03050000: # We don't use .format() and print_function here just in case someone # still has < 2.6 installed. # pylint: disable=bad-builtin version_str = '.'.join(map(str, sys.version_info[:3])) - text = ("At least Python 3.4 is required to run qutebrowser, but " + + text = ("At least Python 3.5 is required to run qutebrowser, but " + version_str + " is installed!\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 67d4897f0..abc981d75 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.4 features available. +At this point we can be sure we have all python 3.5 features available. """ try: diff --git a/qutebrowser/misc/sessions.py b/qutebrowser/misc/sessions.py index c4a2ad661..7c42b231b 100644 --- a/qutebrowser/misc/sessions.py +++ b/qutebrowser/misc/sessions.py @@ -32,6 +32,7 @@ from qutebrowser.utils import (standarddir, objreg, qtutils, log, message, from qutebrowser.commands import cmdexc, cmdutils from qutebrowser.config import config, configfiles from qutebrowser.completion.models import miscmodels +from qutebrowser.mainwindow import mainwindow default = object() # Sentinel value @@ -371,7 +372,6 @@ class SessionManager(QObject): name: The name of the session to load. temp: If given, don't set the current session. """ - from qutebrowser.mainwindow import mainwindow path = self._get_session_path(name, check_exists=True) try: with open(path, encoding='utf-8') as f: diff --git a/qutebrowser/utils/typing.py b/qutebrowser/utils/typing.py deleted file mode 100644 index 358a1a5a3..000000000 --- a/qutebrowser/utils/typing.py +++ /dev/null @@ -1,68 +0,0 @@ -# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: - -# Copyright 2016-2017 Florian Bruhin (The Compiler) -# -# This file is part of qutebrowser. -# -# qutebrowser is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# qutebrowser is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with qutebrowser. If not, see . - -# pylint: disable=unused-import,bad-mcs-method-argument - -"""Wrapper for Python 3.5's typing module. - -This wrapper is needed as both Python 3.5 and typing for PyPI isn't commonly -packaged yet. As we don't actually need anything from the typing module at -runtime, we instead mock the typing classes (using objects to make things -easier) so the typing module isn't a hard dependency. -""" - -# Those are defined here to make them testable easily - - -class FakeTypingMeta(type): - - """Fake typing metaclass like typing.TypingMeta.""" - - def __init__(self, *args, # pylint: disable=super-init-not-called - **_kwds): - pass - - -class FakeUnionMeta(FakeTypingMeta): - - """Fake union metaclass metaclass like typing.UnionMeta.""" - - def __new__(cls, name, bases, namespace, parameters=None): - if parameters is None: - return super().__new__(cls, name, bases, namespace) - self = super().__new__(cls, name, bases, {}) - self.__union_params__ = tuple(parameters) - return self - - def __getitem__(self, parameters): - return self.__class__(self.__name__, self.__bases__, - dict(self.__dict__), parameters=parameters) - - -class FakeUnion(metaclass=FakeUnionMeta): - - """Fake Union type like typing.Union.""" - - __union_params__ = None - - -try: - from typing import Union -except ImportError: # pragma: no cover - Union = FakeUnion diff --git a/qutebrowser/utils/utils.py b/qutebrowser/utils/utils.py index e795cfdd8..23c37a042 100644 --- a/qutebrowser/utils/utils.py +++ b/qutebrowser/utils/utils.py @@ -42,7 +42,7 @@ except ImportError: # pragma: no cover from yaml import SafeLoader as YamlLoader, SafeDumper as YamlDumper import qutebrowser -from qutebrowser.utils import qtutils, log +from qutebrowser.utils import qtutils, log, debug fake_clipboard = None @@ -425,14 +425,13 @@ class KeyInfo: self.text = text def __repr__(self): - # Meh, dependency cycle... - from qutebrowser.utils.debug import qenum_key if self.modifiers is None: modifiers = None else: #modifiers = qflags_key(Qt, self.modifiers) modifiers = hex(int(self.modifiers)) - return get_repr(self, constructor=True, key=qenum_key(Qt, self.key), + return get_repr(self, constructor=True, + key=debug.qenum_key(Qt, self.key), modifiers=modifiers, text=self.text) def __eq__(self, other): @@ -814,10 +813,12 @@ def open_file(filename, cmdline=None): the filename is appended to the cmdline. """ # Import late to avoid circular imports: - # utils -> config -> configdata -> configtypes -> cmdutils -> command -> - # utils - from qutebrowser.misc import guiprocess + # - usertypes -> utils -> guiprocess -> message -> usertypes + # - usertypes -> utils -> config -> configdata -> configtypes -> + # cmdutils -> command -> message -> usertypes from qutebrowser.config import config + from qutebrowser.misc import guiprocess + # the default program to open downloads with - will be empty string # if we want to use the default override = config.val.downloads.open_dispatcher diff --git a/scripts/dev/check_coverage.py b/scripts/dev/check_coverage.py index f53769f8b..0848c404b 100644 --- a/scripts/dev/check_coverage.py +++ b/scripts/dev/check_coverage.py @@ -149,8 +149,6 @@ PERFECT_FILES = [ 'utils/jinja.py'), ('tests/unit/utils/test_error.py', 'utils/error.py'), - ('tests/unit/utils/test_typing.py', - 'utils/typing.py'), ('tests/unit/utils/test_javascript.py', 'utils/javascript.py'), @@ -291,7 +289,7 @@ def main_check_all(): tests. This runs pytest with the used executable, so check_coverage.py should be - called with something like ./.tox/py34/bin/python. + called with something like ./.tox/py36/bin/python. """ for test_file, src_file in PERFECT_FILES: if test_file is None: diff --git a/scripts/dev/ci/travis_backtrace.sh b/scripts/dev/ci/travis_backtrace.sh index 764c36116..c94d1ff06 100644 --- a/scripts/dev/ci/travis_backtrace.sh +++ b/scripts/dev/ci/travis_backtrace.sh @@ -5,10 +5,6 @@ # case $TESTENV in - py34-cov) - exe=/usr/bin/python3.4 - full=full - ;; py3*-pyqt*) exe=$(readlink -f .tox/$TESTENV/bin/python) full= diff --git a/scripts/setupcommon.py b/scripts/setupcommon.py index 494ab4c46..f615ad155 100644 --- a/scripts/setupcommon.py +++ b/scripts/setupcommon.py @@ -121,7 +121,8 @@ setupdata = { 'Operating System :: Microsoft :: Windows :: Windows 7', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', 'Topic :: Internet', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Internet :: WWW/HTTP :: Browsers', diff --git a/tests/end2end/test_invocations.py b/tests/end2end/test_invocations.py index abc9928c9..a59ea5db7 100644 --- a/tests/end2end/test_invocations.py +++ b/tests/end2end/test_invocations.py @@ -265,7 +265,7 @@ def test_launching_with_python2(): pytest.skip("python2 not found") _stdout, stderr = proc.communicate() assert proc.returncode == 1 - error = "At least Python 3.4 is required to run qutebrowser" + error = "At least Python 3.5 is required to run qutebrowser" assert stderr.decode('ascii').startswith(error) diff --git a/tests/unit/commands/test_cmdutils.py b/tests/unit/commands/test_cmdutils.py index 6d610d7b0..2da13881c 100644 --- a/tests/unit/commands/test_cmdutils.py +++ b/tests/unit/commands/test_cmdutils.py @@ -24,11 +24,12 @@ import sys import logging import types +import typing import pytest from qutebrowser.commands import cmdutils, cmdexc, argparser, command -from qutebrowser.utils import usertypes, typing +from qutebrowser.utils import usertypes @pytest.fixture(autouse=True) diff --git a/tests/unit/misc/test_checkpyver.py b/tests/unit/misc/test_checkpyver.py index aeab032e7..a25e1d187 100644 --- a/tests/unit/misc/test_checkpyver.py +++ b/tests/unit/misc/test_checkpyver.py @@ -28,7 +28,7 @@ import pytest from qutebrowser.misc import checkpyver -TEXT = (r"At least Python 3.4 is required to run qutebrowser, but " +TEXT = (r"At least Python 3.5 is required to run qutebrowser, but " r"\d+\.\d+\.\d+ is installed!\n") @@ -60,7 +60,7 @@ def test_patched_no_errwindow(capfd, monkeypatch): """Test with a patched sys.hexversion and --no-err-windows.""" monkeypatch.setattr(checkpyver.sys, 'argv', [sys.argv[0], '--no-err-windows']) - monkeypatch.setattr(checkpyver.sys, 'hexversion', 0x03000000) + monkeypatch.setattr(checkpyver.sys, 'hexversion', 0x03040000) monkeypatch.setattr(checkpyver.sys, 'exit', lambda status: None) checkpyver.check_python_version() stdout, stderr = capfd.readouterr() @@ -70,7 +70,7 @@ def test_patched_no_errwindow(capfd, monkeypatch): def test_patched_errwindow(capfd, mocker, monkeypatch): """Test with a patched sys.hexversion and a fake Tk.""" - monkeypatch.setattr(checkpyver.sys, 'hexversion', 0x03000000) + monkeypatch.setattr(checkpyver.sys, 'hexversion', 0x03040000) monkeypatch.setattr(checkpyver.sys, 'exit', lambda status: None) try: diff --git a/tests/unit/utils/test_typing.py b/tests/unit/utils/test_typing.py deleted file mode 100644 index 4a3359a45..000000000 --- a/tests/unit/utils/test_typing.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2016-2017 Florian Bruhin (The Compiler) -# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: - -# -# qutebrowser is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# qutebrowser is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with qutebrowser. If not, see . - -"""Tests for qutebrowser.utils.typing.""" - -import pytest - -from qutebrowser.utils import typing - - -@pytest.fixture -def pytyping(): - """A fixture to get the python 3.5+ typing module.""" - pytyping = pytest.importorskip('typing') - return pytyping - - -class TestUnion: - - def test_python_subclass(self, pytyping): - assert (type(pytyping.Union[str, int]) is # flake8: disable=E721 - type(pytyping.Union)) - - def test_qute_subclass(self): - assert (type(typing.FakeUnion[str, int]) is # flake8: disable=E721 - type(typing.FakeUnion)) - - def test_python_params(self, pytyping): - union = pytyping.Union[str, int] - try: - assert union.__union_params__ == (str, int) - except AttributeError: - assert union.__args__ == (str, int) - - def test_qute_params(self): - union = typing.FakeUnion[str, int] - try: - assert union.__union_params__ == (str, int) - except AttributeError: - assert union.__args__ == (str, int)