diff --git a/misc/requirements/requirements-flake8.txt b/misc/requirements/requirements-flake8.txt index 3128e63d8..7410107a1 100644 --- a/misc/requirements/requirements-flake8.txt +++ b/misc/requirements/requirements-flake8.txt @@ -2,7 +2,7 @@ attrs==19.1.0 entrypoints==0.3 -flake8==3.7.7 +flake8==3.7.8 flake8-bugbear==19.3.0 flake8-builtins==1.4.1 flake8-comprehensions==2.1.0 @@ -19,7 +19,7 @@ flake8-tuple==0.4.0 mccabe==0.6.1 pep8-naming==0.8.2 pycodestyle==2.5.0 -pydocstyle==3.0.0 +pydocstyle==3.0.0 # rq.filter: < 4 pyflakes==2.1.1 six==1.12.0 snowballstemmer==1.9.0 diff --git a/misc/requirements/requirements-flake8.txt-raw b/misc/requirements/requirements-flake8.txt-raw index 1bdca6974..1bc691a77 100644 --- a/misc/requirements/requirements-flake8.txt-raw +++ b/misc/requirements/requirements-flake8.txt-raw @@ -12,5 +12,8 @@ flake8-string-format flake8-tidy-imports flake8-tuple pep8-naming -pydocstyle +pydocstyle < 4 pyflakes + +# WORKAROUND for https://gitlab.com/pycqa/flake8-docstrings/issues/36 +#@ filter: pydocstyle < 4 diff --git a/misc/requirements/requirements-mypy.txt b/misc/requirements/requirements-mypy.txt index eac1123af..4d68606dc 100644 --- a/misc/requirements/requirements-mypy.txt +++ b/misc/requirements/requirements-mypy.txt @@ -1,8 +1,9 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py -mypy==0.711 +mypy==0.720 mypy-extensions==0.4.1 # PyQt5==5.11.3 -# PyQt5-sip==4.19.17 +# PyQt5-sip==4.19.18 -e git+https://github.com/qutebrowser/PyQt5-stubs.git@wip#egg=PyQt5_stubs typed-ast==1.4.0 +typing-extensions==3.7.4 diff --git a/misc/requirements/requirements-pip.txt b/misc/requirements/requirements-pip.txt index e2336bba6..52eb8fad2 100644 --- a/misc/requirements/requirements-pip.txt +++ b/misc/requirements/requirements-pip.txt @@ -2,7 +2,7 @@ appdirs==1.4.3 packaging==19.0 -pyparsing==2.4.0 +pyparsing==2.4.2 setuptools==41.0.1 six==1.12.0 wheel==0.33.4 diff --git a/misc/requirements/requirements-pyqt.txt b/misc/requirements/requirements-pyqt.txt index be65f9815..0e8bcd476 100644 --- a/misc/requirements/requirements-pyqt.txt +++ b/misc/requirements/requirements-pyqt.txt @@ -2,4 +2,4 @@ PyQt5==5.13.0 PyQt5-sip==4.19.18 -PyQtWebEngine==5.12.1 +PyQtWebEngine==5.13.0 diff --git a/misc/requirements/requirements-pyroma.txt b/misc/requirements/requirements-pyroma.txt index 608ff3944..a48aafaad 100644 --- a/misc/requirements/requirements-pyroma.txt +++ b/misc/requirements/requirements-pyroma.txt @@ -1,4 +1,4 @@ # This file is automatically generated by scripts/dev/recompile_requirements.py -docutils==0.14 +docutils==0.15 pyroma==2.5 diff --git a/misc/requirements/requirements-sphinx.txt b/misc/requirements/requirements-sphinx.txt index 97852e55e..e862537bf 100644 --- a/misc/requirements/requirements-sphinx.txt +++ b/misc/requirements/requirements-sphinx.txt @@ -4,14 +4,14 @@ alabaster==0.7.12 Babel==2.7.0 certifi==2019.6.16 chardet==3.0.4 -docutils==0.14 +docutils==0.15 idna==2.8 imagesize==1.1.0 Jinja2==2.10.1 MarkupSafe==1.1.1 packaging==19.0 Pygments==2.4.2 -pyparsing==2.4.0 +pyparsing==2.4.2 pytz==2019.1 requests==2.22.0 six==1.12.0 diff --git a/misc/requirements/requirements-tests.txt b/misc/requirements/requirements-tests.txt index f63b687ea..3464be25a 100644 --- a/misc/requirements/requirements-tests.txt +++ b/misc/requirements/requirements-tests.txt @@ -3,32 +3,32 @@ atomicwrites==1.3.0 attrs==19.1.0 backports.functools-lru-cache==1.5 -beautifulsoup4==4.7.1 +beautifulsoup4==4.8.0 cheroot==6.5.5 Click==7.0 # colorama==0.4.1 coverage==4.5.3 EasyProcess==0.2.7 -Flask==1.0.3 +Flask==1.1.1 glob2==0.7 hunter==3.0.1 -hypothesis==4.24.6 +hypothesis==4.28.2 importlib-metadata==0.18 itsdangerous==1.1.0 # Jinja2==2.10.1 -Mako==1.0.13 +Mako==1.0.14 manhole==1.6.0 # MarkupSafe==1.1.1 -more-itertools==7.1.0 +more-itertools==7.2.0 packaging==19.0 parse==1.12.0 -parse-type==0.4.2 +parse-type==0.5.2 pluggy==0.12.0 py==1.8.0 py-cpuinfo==5.0.0 -pyparsing==2.4.0 -pytest==5.0.0 -pytest-bdd==3.1.0 +pyparsing==2.4.2 +pytest==5.0.1 +pytest-bdd==3.1.1 pytest-benchmark==3.2.2 pytest-cov==2.7.1 pytest-instafail==0.4.1 @@ -43,5 +43,5 @@ six==1.12.0 soupsieve==1.9.2 vulture==1.0 wcwidth==0.1.7 -Werkzeug==0.15.4 -zipp==0.5.1 +Werkzeug==0.15.5 +zipp==0.5.2 diff --git a/misc/requirements/requirements-tox.txt b/misc/requirements/requirements-tox.txt index a4ab4892b..8ed7493dd 100644 --- a/misc/requirements/requirements-tox.txt +++ b/misc/requirements/requirements-tox.txt @@ -5,10 +5,10 @@ importlib-metadata==0.18 packaging==19.0 pluggy==0.12.0 py==1.8.0 -pyparsing==2.4.0 +pyparsing==2.4.2 six==1.12.0 toml==0.10.0 tox==3.13.2 tox-venv==0.4.0 -virtualenv==16.6.1 +virtualenv==16.6.2 zipp==0.5.2 diff --git a/mypy.ini b/mypy.ini index 0607ddfdf..1880921b9 100644 --- a/mypy.ini +++ b/mypy.ini @@ -17,6 +17,7 @@ disallow_untyped_decorators = True # check_untyped_defs = True # no_implicit_optional = True # warn_return_any = True +warn_unreachable = True # Other strictness flags strict_equality = True diff --git a/qutebrowser/browser/browsertab.py b/qutebrowser/browser/browsertab.py index 67fad967c..a5e1650e4 100644 --- a/qutebrowser/browser/browsertab.py +++ b/qutebrowser/browser/browsertab.py @@ -788,7 +788,9 @@ class AbstractTabPrivate: if cur_mode == usertypes.KeyMode.insert: return - def _auto_insert_mode_cb(elem: 'webelem.AbstractWebElement') -> None: + def _auto_insert_mode_cb( + elem: typing.Optional['webelem.AbstractWebElement'] + ) -> None: """Called from JS after finding the focused element.""" if elem is None: log.webview.debug("No focused element!") diff --git a/qutebrowser/browser/webengine/webenginesettings.py b/qutebrowser/browser/webengine/webenginesettings.py index 84ad5d04b..7ccdc160d 100644 --- a/qutebrowser/browser/webengine/webenginesettings.py +++ b/qutebrowser/browser/webengine/webenginesettings.py @@ -26,6 +26,7 @@ Module attributes: import os import operator +import typing # pylint: disable=unused-import,useless-suppression from PyQt5.QtGui import QFont from PyQt5.QtWebEngineWidgets import (QWebEngineSettings, QWebEngineProfile, @@ -37,9 +38,9 @@ from qutebrowser.config.websettings import AttributeInfo as Attr from qutebrowser.utils import utils, standarddir, qtutils, message, log # The default QWebEngineProfile -default_profile = None +default_profile = None # type: typing.Optional[QWebEngineProfile] # The QWebEngineProfile used for private (off-the-record) windows -private_profile = None +private_profile = None # type: typing.Optional[QWebEngineProfile] # The global WebEngineSettings object global_settings = None diff --git a/qutebrowser/browser/webkit/webkitelem.py b/qutebrowser/browser/webkit/webkitelem.py index 983904eeb..3b65fc7a6 100644 --- a/qutebrowser/browser/webkit/webkitelem.py +++ b/qutebrowser/browser/webkit/webkitelem.py @@ -172,7 +172,8 @@ class WebKitElement(webelem.AbstractWebElement): def _parent(self) -> typing.Optional['WebKitElement']: """Get the parent element of this element.""" self._check_vanished() - elem = self._elem.parent() + elem = typing.cast(typing.Optional[QWebElement], + self._elem.parent()) if elem is None or elem.isNull(): return None return WebKitElement(elem, tab=self._tab) diff --git a/qutebrowser/commands/command.py b/qutebrowser/commands/command.py index 044816fdb..02d546228 100644 --- a/qutebrowser/commands/command.py +++ b/qutebrowser/commands/command.py @@ -203,7 +203,7 @@ class Command: else: raise TypeError("{}: Invalid value={!r} for argument '{}'!" .format(self.name, arg_info.value, param.name)) - return False + raise utils.Unreachable def _inspect_func(self): """Inspect the function to get useful information from it. diff --git a/qutebrowser/components/misccommands.py b/qutebrowser/components/misccommands.py index fc5fce225..afc79e0a7 100644 --- a/qutebrowser/components/misccommands.py +++ b/qutebrowser/components/misccommands.py @@ -23,6 +23,7 @@ import os import signal import functools import logging +import typing try: import hunter @@ -37,7 +38,8 @@ from qutebrowser.api import cmdutils, apitypes, message, config @cmdutils.register(name='reload') @cmdutils.argument('tab', value=cmdutils.Value.count_tab) -def reloadpage(tab: apitypes.Tab, force: bool = False) -> None: +def reloadpage(tab: typing.Optional[apitypes.Tab], + force: bool = False) -> None: """Reload the current/[count]th tab. Args: @@ -50,7 +52,7 @@ def reloadpage(tab: apitypes.Tab, force: bool = False) -> None: @cmdutils.register() @cmdutils.argument('tab', value=cmdutils.Value.count_tab) -def stop(tab: apitypes.Tab) -> None: +def stop(tab: typing.Optional[apitypes.Tab]) -> None: """Stop loading in the current/[count]th tab. Args: @@ -90,7 +92,7 @@ def _print_pdf(tab: apitypes.Tab, filename: str) -> None: @cmdutils.register(name='print') @cmdutils.argument('tab', value=cmdutils.Value.count_tab) @cmdutils.argument('pdf', flag='f', metavar='file') -def printpage(tab: apitypes.Tab, +def printpage(tab: typing.Optional[apitypes.Tab], preview: bool = False, *, pdf: str = None) -> None: """Print the current/[count]th tab. @@ -156,7 +158,7 @@ def insert_text(tab: apitypes.Tab, text: str) -> None: Args: text: The text to insert. """ - def _insert_text_cb(elem: apitypes.WebElement) -> None: + def _insert_text_cb(elem: typing.Optional[apitypes.WebElement]) -> None: if elem is None: message.error("No element focused!") return @@ -188,7 +190,7 @@ def click_element(tab: apitypes.Tab, filter_: str, value: str, *, target: How to open the clicked element (normal/tab/tab-bg/window). force_event: Force generating a fake click event. """ - def single_cb(elem: apitypes.WebElement) -> None: + def single_cb(elem: typing.Optional[apitypes.WebElement]) -> None: """Click a single element.""" if elem is None: message.error("No element found with id {}!".format(value)) @@ -229,7 +231,7 @@ def debug_webaction(tab: apitypes.Tab, action: str, count: int = 1) -> None: @cmdutils.register() @cmdutils.argument('tab', value=cmdutils.Value.count_tab) -def tab_mute(tab: apitypes.Tab) -> None: +def tab_mute(tab: typing.Optional[apitypes.Tab]) -> None: """Mute/Unmute the current/[count]th tab. Args: diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py index 4eb6f2a1f..4159e1aec 100644 --- a/qutebrowser/config/config.py +++ b/qutebrowser/config/config.py @@ -187,7 +187,7 @@ class KeyConfig: def get_command(self, key: keyutils.KeySequence, mode: str, - default: bool = False) -> str: + default: bool = False) -> typing.Optional[str]: """Get the command for a given key (or None).""" self._validate(key, mode) if default: @@ -202,7 +202,7 @@ class KeyConfig: mode: str, save_yaml: bool = False) -> None: """Add a new binding from key to command.""" - if command is not None and not command.strip(): + if not command.strip(): raise configexc.KeybindingError( "Can't add binding '{}' with empty command in {} " 'mode'.format(key, mode)) diff --git a/qutebrowser/config/configtypes.py b/qutebrowser/config/configtypes.py index e43871ca6..de26d8321 100644 --- a/qutebrowser/config/configtypes.py +++ b/qutebrowser/config/configtypes.py @@ -740,7 +740,7 @@ class BoolAsk(Bool): value: str) -> typing.Union[bool, str, None]: # basic validation unneeded if it's == 'ask' and done by Bool if we # call super().from_str - if isinstance(value, str) and value.lower() == 'ask': + if value.lower() == 'ask': return 'ask' return super().from_str(value) @@ -1147,7 +1147,7 @@ class Font(BaseType): """ # Gets set when the config is initialized. - monospace_fonts = None + monospace_fonts = None # type: str font_regex = re.compile(r""" ( ( @@ -1329,7 +1329,7 @@ class Regex(BaseType): def to_py( self, - value: typing.Union[str, typing.Pattern[str]] + value: typing.Union[str, typing.Pattern[str], configutils.Unset] ) -> typing.Union[configutils.Unset, None, typing.Pattern[str]]: """Get a compiled regex from either a string or a regex object.""" self._basic_py_validation(value, (str, self._regex_type)) diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py index 7f6201f88..03fe6418c 100644 --- a/qutebrowser/mainwindow/tabwidget.py +++ b/qutebrowser/mainwindow/tabwidget.py @@ -19,6 +19,7 @@ """The tab widget used for TabbedBrowser from browser.py.""" +import typing import functools import contextlib @@ -347,7 +348,8 @@ class TabWidget(QTabWidget): def setTabIcon(self, idx: int, icon: QIcon): """Always show tab icons for pinned tabs in some circumstances.""" - tab = self.widget(idx) + tab = typing.cast(typing.Optional[browsertab.AbstractTab], + self.widget(idx)) if (icon.isNull() and config.cache['tabs.favicons.show'] != 'never' and config.cache['tabs.pinned.shrink'] and diff --git a/qutebrowser/misc/checkpyver.py b/qutebrowser/misc/checkpyver.py index aab373648..597b2597c 100644 --- a/qutebrowser/misc/checkpyver.py +++ b/qutebrowser/misc/checkpyver.py @@ -49,7 +49,8 @@ def check_python_version(): version_str = '.'.join(map(str, sys.version_info[:3])) text = ("At least Python 3.5 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 + if (Tk and # type: ignore + '--no-err-windows' not in sys.argv): # pragma: no cover root = Tk() root.withdraw() messagebox.showerror("qutebrowser: Fatal error!", text) diff --git a/qutebrowser/misc/crashsignal.py b/qutebrowser/misc/crashsignal.py index 6bbd480f1..c645f19fd 100644 --- a/qutebrowser/misc/crashsignal.py +++ b/qutebrowser/misc/crashsignal.py @@ -172,7 +172,7 @@ class CrashHandler(QObject): if sys.__stderr__ is not None: faulthandler.enable(sys.__stderr__) else: - faulthandler.disable() + faulthandler.disable() # type: ignore try: self._crash_log_file.close() os.remove(self._crash_log_file.name) diff --git a/qutebrowser/utils/log.py b/qutebrowser/utils/log.py index 004ce16c0..4d32d8222 100644 --- a/qutebrowser/utils/log.py +++ b/qutebrowser/utils/log.py @@ -259,7 +259,7 @@ def _init_handlers(level, color, force_color, json_logging, ram_capacity): level, color, force_color, json_logging) if sys.stderr is None: - console_handler = None + console_handler = None # type: ignore else: strip = False if force_color else None if use_colorama: @@ -313,7 +313,7 @@ def _init_formatters(level, color, force_color, json_logging): html_formatter = HTMLFormatter(EXTENDED_FMT_HTML, DATEFMT, log_colors=LOG_COLORS) if sys.stderr is None: - return None, ram_formatter, html_formatter, False + return None, ram_formatter, html_formatter, False # type: ignore if json_logging: console_formatter = JSONFormatter() diff --git a/qutebrowser/utils/version.py b/qutebrowser/utils/version.py index 437ba49a3..615522c05 100644 --- a/qutebrowser/utils/version.py +++ b/qutebrowser/utils/version.py @@ -352,9 +352,9 @@ def _chromium_version(): Also see https://www.chromium.org/developers/calendar and https://chromereleases.googleblog.com/ """ - if webenginesettings is None or QWebEngineProfile is None: + if webenginesettings is None or QWebEngineProfile is None: # type: ignore # This should never happen - return 'unavailable' + return 'unavailable' # type: ignore ua = webenginesettings.default_user_agent if ua is None: profile = QWebEngineProfile.defaultProfile()