Merge branch 'mypy'
This commit is contained in:
commit
07c632869d
@ -38,9 +38,11 @@ matrix:
|
|||||||
# env: TESTENV=py35 OSX=yosemite
|
# env: TESTENV=py35 OSX=yosemite
|
||||||
# osx_image: xcode6.4
|
# osx_image: xcode6.4
|
||||||
- os: linux
|
- os: linux
|
||||||
env: TESTENV=pylint PYTHON=python3.6
|
env: TESTENV=pylint
|
||||||
- os: linux
|
- os: linux
|
||||||
env: TESTENV=flake8
|
env: TESTENV=flake8
|
||||||
|
- os: linux
|
||||||
|
env: TESTENV=mypy
|
||||||
- os: linux
|
- os: linux
|
||||||
env: TESTENV=docs
|
env: TESTENV=docs
|
||||||
addons:
|
addons:
|
||||||
|
@ -32,6 +32,7 @@ include doc/changelog.asciidoc
|
|||||||
prune tests
|
prune tests
|
||||||
prune qutebrowser/3rdparty
|
prune qutebrowser/3rdparty
|
||||||
exclude pytest.ini
|
exclude pytest.ini
|
||||||
|
exclude mypy.ini
|
||||||
exclude qutebrowser/javascript/.eslintrc.yaml
|
exclude qutebrowser/javascript/.eslintrc.yaml
|
||||||
exclude qutebrowser/javascript/.eslintignore
|
exclude qutebrowser/javascript/.eslintignore
|
||||||
exclude doc/help
|
exclude doc/help
|
||||||
|
@ -66,6 +66,7 @@ Fixed
|
|||||||
like GMail. However, the default for `content.cookies.accept` is still `all`
|
like GMail. However, the default for `content.cookies.accept` is still `all`
|
||||||
to be in line with what other browsers do.
|
to be in line with what other browsers do.
|
||||||
- `:navigate` not incrementing in anchors or queries or anchors.
|
- `:navigate` not incrementing in anchors or queries or anchors.
|
||||||
|
- Crash when trying to use a proxy requiring authentication with QtWebKit.
|
||||||
|
|
||||||
v1.5.2
|
v1.5.2
|
||||||
------
|
------
|
||||||
|
8
misc/requirements/requirements-mypy.txt
Normal file
8
misc/requirements/requirements-mypy.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# This file is automatically generated by scripts/dev/recompile_requirements.py
|
||||||
|
|
||||||
|
mypy==0.641
|
||||||
|
mypy-extensions==0.4.1
|
||||||
|
PyQt5==5.11.3
|
||||||
|
PyQt5-sip==4.19.13
|
||||||
|
-e git+https://github.com/qutebrowser/PyQt5-stubs.git@wip#egg=PyQt5_stubs
|
||||||
|
typed-ast==1.1.0
|
5
misc/requirements/requirements-mypy.txt-raw
Normal file
5
misc/requirements/requirements-mypy.txt-raw
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
mypy
|
||||||
|
-e git+https://github.com/qutebrowser/PyQt5-stubs.git@wip#egg=PyQt5-stubs
|
||||||
|
|
||||||
|
# remove @commit-id for scm installs
|
||||||
|
#@ replace: @.*# @wip#
|
7
misc/requirements/requirements-optional.txt
Normal file
7
misc/requirements/requirements-optional.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# This file is automatically generated by scripts/dev/recompile_requirements.py
|
||||||
|
|
||||||
|
colorama==0.4.0
|
||||||
|
cssutils==1.0.2
|
||||||
|
hunter==2.1.0
|
||||||
|
Pympler==0.6
|
||||||
|
six==1.11.0
|
3
misc/requirements/requirements-optional.txt-raw
Normal file
3
misc/requirements/requirements-optional.txt-raw
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
hunter
|
||||||
|
cssutils
|
||||||
|
pympler
|
51
mypy.ini
Normal file
51
mypy.ini
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
[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
|
||||||
|
warn_redundant_casts = True
|
||||||
|
warn_unused_ignores = True
|
||||||
|
disallow_subclassing_any = True
|
||||||
|
## https://github.com/python/mypy/issues/5957
|
||||||
|
# warn_unused_configs = True
|
||||||
|
# disallow_untyped_calls = True
|
||||||
|
# disallow_untyped_defs = True
|
||||||
|
## https://github.com/python/mypy/issues/5954
|
||||||
|
# disallow_incomplete_defs = True
|
||||||
|
# check_untyped_defs = True
|
||||||
|
# disallow_untyped_decorators = True
|
||||||
|
# no_implicit_optional = True
|
||||||
|
# warn_return_any = True
|
||||||
|
|
||||||
|
[mypy-faulthandler]
|
||||||
|
# https://github.com/python/typeshed/pull/2627
|
||||||
|
ignore_missing_imports = True
|
||||||
|
|
||||||
|
[mypy-colorama]
|
||||||
|
# https://github.com/tartley/colorama/issues/206
|
||||||
|
ignore_missing_imports = True
|
||||||
|
|
||||||
|
[mypy-hunter]
|
||||||
|
# https://github.com/ionelmc/python-hunter/issues/43
|
||||||
|
ignore_missing_imports = True
|
||||||
|
|
||||||
|
[mypy-pygments.*]
|
||||||
|
# https://bitbucket.org/birkenfeld/pygments-main/issues/1485/type-hints
|
||||||
|
ignore_missing_imports = True
|
||||||
|
|
||||||
|
[mypy-cssutils]
|
||||||
|
# Pretty much inactive currently
|
||||||
|
ignore_missing_imports = True
|
||||||
|
|
||||||
|
[mypy-pypeg2]
|
||||||
|
# Pretty much inactive currently
|
||||||
|
ignore_missing_imports = True
|
||||||
|
|
||||||
|
[mypy-bdb]
|
||||||
|
# stdlib, missing in typeshed
|
||||||
|
ignore_missing_imports = True
|
||||||
|
|
||||||
|
[mypy-qutebrowser.browser.webkit.rfc6266]
|
||||||
|
# subclasses dynamic PyPEG2 classes
|
||||||
|
disallow_subclassing_any = False
|
@ -136,8 +136,8 @@ class AbstractAction:
|
|||||||
action_base: The type of the actions (QWeb{Engine,}Page.WebAction)
|
action_base: The type of the actions (QWeb{Engine,}Page.WebAction)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
action_class = None
|
action_class = None # type: type
|
||||||
action_base = None
|
action_base = None # type: type
|
||||||
|
|
||||||
def __init__(self, tab):
|
def __init__(self, tab):
|
||||||
self._widget = None
|
self._widget = None
|
||||||
@ -685,7 +685,7 @@ class AbstractAudio(QObject):
|
|||||||
self._widget = None
|
self._widget = None
|
||||||
self._tab = tab
|
self._tab = tab
|
||||||
|
|
||||||
def set_muted(self, muted: bool, override: bool = False):
|
def set_muted(self, muted: bool, override: bool = False) -> None:
|
||||||
"""Set this tab as muted or not.
|
"""Set this tab as muted or not.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
@ -699,7 +699,7 @@ class AbstractAudio(QObject):
|
|||||||
"""Whether this tab is muted."""
|
"""Whether this tab is muted."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def toggle_muted(self, *, override: bool = False):
|
def toggle_muted(self, *, override: bool = False) -> None:
|
||||||
self.set_muted(not self.is_muted(), override=override)
|
self.set_muted(not self.is_muted(), override=override)
|
||||||
|
|
||||||
def is_recently_audible(self):
|
def is_recently_audible(self):
|
||||||
|
@ -75,7 +75,7 @@ class CommandDispatcher:
|
|||||||
new_window.show()
|
new_window.show()
|
||||||
return new_window.tabbed_browser
|
return new_window.tabbed_browser
|
||||||
|
|
||||||
def _count(self):
|
def _count(self) -> int:
|
||||||
"""Convenience method to get the widget count."""
|
"""Convenience method to get the widget count."""
|
||||||
return self._tabbed_browser.widget.count()
|
return self._tabbed_browser.widget.count()
|
||||||
|
|
||||||
@ -513,7 +513,8 @@ class CommandDispatcher:
|
|||||||
@cmdutils.register(instance='command-dispatcher', scope='window')
|
@cmdutils.register(instance='command-dispatcher', scope='window')
|
||||||
@cmdutils.argument('win_id', completion=miscmodels.window)
|
@cmdutils.argument('win_id', completion=miscmodels.window)
|
||||||
@cmdutils.argument('count', count=True)
|
@cmdutils.argument('count', count=True)
|
||||||
def tab_give(self, win_id: int = None, keep=False, count=None):
|
def tab_give(self, win_id: int = None, keep: bool = False,
|
||||||
|
count: int = None) -> None:
|
||||||
"""Give the current tab to a new or existing window if win_id given.
|
"""Give the current tab to a new or existing window if win_id given.
|
||||||
|
|
||||||
If no win_id is given, the tab will get detached into a new window.
|
If no win_id is given, the tab will get detached into a new window.
|
||||||
@ -601,7 +602,8 @@ class CommandDispatcher:
|
|||||||
@cmdutils.argument('where', choices=['prev', 'next', 'up', 'increment',
|
@cmdutils.argument('where', choices=['prev', 'next', 'up', 'increment',
|
||||||
'decrement'])
|
'decrement'])
|
||||||
@cmdutils.argument('count', count=True)
|
@cmdutils.argument('count', count=True)
|
||||||
def navigate(self, where: str, tab=False, bg=False, window=False, count=1):
|
def navigate(self, where: str, tab: bool = False, bg: bool = False,
|
||||||
|
window: bool = False, count: int = 1) -> None:
|
||||||
"""Open typical prev/next links or navigate using the URL path.
|
"""Open typical prev/next links or navigate using the URL path.
|
||||||
|
|
||||||
This tries to automatically click on typical _Previous Page_ or
|
This tries to automatically click on typical _Previous Page_ or
|
||||||
@ -645,7 +647,7 @@ class CommandDispatcher:
|
|||||||
inc_or_dec='decrement'),
|
inc_or_dec='decrement'),
|
||||||
'increment': functools.partial(navigate.incdec,
|
'increment': functools.partial(navigate.incdec,
|
||||||
inc_or_dec='increment'),
|
inc_or_dec='increment'),
|
||||||
}
|
} # type: typing.Dict[str, typing.Callable]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if where in ['prev', 'next']:
|
if where in ['prev', 'next']:
|
||||||
@ -665,7 +667,7 @@ class CommandDispatcher:
|
|||||||
|
|
||||||
@cmdutils.register(instance='command-dispatcher', scope='window')
|
@cmdutils.register(instance='command-dispatcher', scope='window')
|
||||||
@cmdutils.argument('count', count=True)
|
@cmdutils.argument('count', count=True)
|
||||||
def scroll_px(self, dx: int, dy: int, count=1):
|
def scroll_px(self, dx: int, dy: int, count: int = 1) -> None:
|
||||||
"""Scroll the current tab by 'count * dx/dy' pixels.
|
"""Scroll the current tab by 'count * dx/dy' pixels.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -681,7 +683,7 @@ class CommandDispatcher:
|
|||||||
|
|
||||||
@cmdutils.register(instance='command-dispatcher', scope='window')
|
@cmdutils.register(instance='command-dispatcher', scope='window')
|
||||||
@cmdutils.argument('count', count=True)
|
@cmdutils.argument('count', count=True)
|
||||||
def scroll(self, direction: typing.Union[str, int], count=1):
|
def scroll(self, direction: str, count: int = 1) -> None:
|
||||||
"""Scroll the current tab in the given direction.
|
"""Scroll the current tab in the given direction.
|
||||||
|
|
||||||
Note you can use `:run-with-count` to have a keybinding with a bigger
|
Note you can use `:run-with-count` to have a keybinding with a bigger
|
||||||
@ -719,7 +721,8 @@ class CommandDispatcher:
|
|||||||
@cmdutils.register(instance='command-dispatcher', scope='window')
|
@cmdutils.register(instance='command-dispatcher', scope='window')
|
||||||
@cmdutils.argument('count', count=True)
|
@cmdutils.argument('count', count=True)
|
||||||
@cmdutils.argument('horizontal', flag='x')
|
@cmdutils.argument('horizontal', flag='x')
|
||||||
def scroll_to_perc(self, perc: float = None, horizontal=False, count=None):
|
def scroll_to_perc(self, perc: float = None, horizontal: bool = False,
|
||||||
|
count: int = None) -> None:
|
||||||
"""Scroll to a specific percentage of the page.
|
"""Scroll to a specific percentage of the page.
|
||||||
|
|
||||||
The percentage can be given either as argument or as count.
|
The percentage can be given either as argument or as count.
|
||||||
@ -764,7 +767,7 @@ class CommandDispatcher:
|
|||||||
choices=('next', 'increment'))
|
choices=('next', 'increment'))
|
||||||
def scroll_page(self, x: float, y: float, *,
|
def scroll_page(self, x: float, y: float, *,
|
||||||
top_navigate: str = None, bottom_navigate: str = None,
|
top_navigate: str = None, bottom_navigate: str = None,
|
||||||
count=1):
|
count: int = 1) -> None:
|
||||||
"""Scroll the frame page-wise.
|
"""Scroll the frame page-wise.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -1120,7 +1123,7 @@ class CommandDispatcher:
|
|||||||
@cmdutils.argument('index', choices=['last'])
|
@cmdutils.argument('index', choices=['last'])
|
||||||
@cmdutils.argument('count', count=True)
|
@cmdutils.argument('count', count=True)
|
||||||
def tab_focus(self, index: typing.Union[str, int] = None,
|
def tab_focus(self, index: typing.Union[str, int] = None,
|
||||||
count=None, no_last=False):
|
count: int = None, no_last: bool = False) -> None:
|
||||||
"""Select the tab given as argument/[count].
|
"""Select the tab given as argument/[count].
|
||||||
|
|
||||||
If neither count nor index are given, it behaves like tab-next.
|
If neither count nor index are given, it behaves like tab-next.
|
||||||
@ -1143,6 +1146,8 @@ class CommandDispatcher:
|
|||||||
self.tab_next()
|
self.tab_next()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
assert isinstance(index, int)
|
||||||
|
|
||||||
if index < 0:
|
if index < 0:
|
||||||
index = self._count() + index + 1
|
index = self._count() + index + 1
|
||||||
|
|
||||||
@ -1159,7 +1164,8 @@ class CommandDispatcher:
|
|||||||
@cmdutils.register(instance='command-dispatcher', scope='window')
|
@cmdutils.register(instance='command-dispatcher', scope='window')
|
||||||
@cmdutils.argument('index', choices=['+', '-'])
|
@cmdutils.argument('index', choices=['+', '-'])
|
||||||
@cmdutils.argument('count', count=True)
|
@cmdutils.argument('count', count=True)
|
||||||
def tab_move(self, index: typing.Union[str, int] = None, count=None):
|
def tab_move(self, index: typing.Union[str, int] = None,
|
||||||
|
count: int = None) -> None:
|
||||||
"""Move the current tab according to the argument and [count].
|
"""Move the current tab according to the argument and [count].
|
||||||
|
|
||||||
If neither is given, move it to the first position.
|
If neither is given, move it to the first position.
|
||||||
@ -1188,6 +1194,7 @@ class CommandDispatcher:
|
|||||||
if count is not None:
|
if count is not None:
|
||||||
new_idx = count - 1
|
new_idx = count - 1
|
||||||
elif index is not None:
|
elif index is not None:
|
||||||
|
assert isinstance(index, int)
|
||||||
new_idx = index - 1 if index >= 0 else index + self._count()
|
new_idx = index - 1 if index >= 0 else index + self._count()
|
||||||
else:
|
else:
|
||||||
new_idx = 0
|
new_idx = 0
|
||||||
@ -1715,10 +1722,10 @@ class CommandDispatcher:
|
|||||||
|
|
||||||
@cmdutils.register(instance='command-dispatcher', scope='window')
|
@cmdutils.register(instance='command-dispatcher', scope='window')
|
||||||
@cmdutils.argument('filter_', choices=['id'])
|
@cmdutils.argument('filter_', choices=['id'])
|
||||||
def click_element(self, filter_: str, value, *,
|
def click_element(self, filter_: str, value: str, *,
|
||||||
target: usertypes.ClickTarget =
|
target: usertypes.ClickTarget =
|
||||||
usertypes.ClickTarget.normal,
|
usertypes.ClickTarget.normal,
|
||||||
force_event=False):
|
force_event: bool = False) -> None:
|
||||||
"""Click the element matching the given filter.
|
"""Click the element matching the given filter.
|
||||||
|
|
||||||
The given filter needs to result in exactly one element, otherwise, an
|
The given filter needs to result in exactly one element, otherwise, an
|
||||||
@ -2067,8 +2074,8 @@ class CommandDispatcher:
|
|||||||
|
|
||||||
@cmdutils.register(instance='command-dispatcher', scope='window',
|
@cmdutils.register(instance='command-dispatcher', scope='window',
|
||||||
maxsplit=0, no_cmd_split=True)
|
maxsplit=0, no_cmd_split=True)
|
||||||
def jseval(self, js_code, file=False, quiet=False, *,
|
def jseval(self, js_code: str, file: bool = False, quiet: bool = False, *,
|
||||||
world: typing.Union[usertypes.JsWorld, int] = None):
|
world: typing.Union[usertypes.JsWorld, int] = None) -> None:
|
||||||
"""Evaluate a JavaScript string.
|
"""Evaluate a JavaScript string.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -40,7 +40,11 @@ from qutebrowser.utils import (usertypes, standarddir, utils, message, log,
|
|||||||
from qutebrowser.qt import sip
|
from qutebrowser.qt import sip
|
||||||
|
|
||||||
|
|
||||||
ModelRole = enum.IntEnum('ModelRole', ['item'], start=Qt.UserRole)
|
class ModelRole(enum.IntEnum):
|
||||||
|
|
||||||
|
"""Custom download model roles."""
|
||||||
|
|
||||||
|
item = Qt.UserRole
|
||||||
|
|
||||||
|
|
||||||
# Remember the last used directory
|
# Remember the last used directory
|
||||||
@ -1058,7 +1062,7 @@ class DownloadModel(QAbstractListModel):
|
|||||||
|
|
||||||
@cmdutils.register(instance='download-model', scope='window', maxsplit=0)
|
@cmdutils.register(instance='download-model', scope='window', maxsplit=0)
|
||||||
@cmdutils.argument('count', count=True)
|
@cmdutils.argument('count', count=True)
|
||||||
def download_open(self, cmdline: str = None, count=0):
|
def download_open(self, cmdline: str = None, count: int = 0) -> None:
|
||||||
"""Open the last/[count]th download.
|
"""Open the last/[count]th download.
|
||||||
|
|
||||||
If no specific command is given, this will use the system's default
|
If no specific command is given, this will use the system's default
|
||||||
|
@ -737,7 +737,7 @@ class HintManager(QObject):
|
|||||||
self._context.baseurl = tabbed_browser.current_url()
|
self._context.baseurl = tabbed_browser.current_url()
|
||||||
except qtutils.QtValueError:
|
except qtutils.QtValueError:
|
||||||
raise cmdexc.CommandError("No URL set for this page yet!")
|
raise cmdexc.CommandError("No URL set for this page yet!")
|
||||||
self._context.args = args
|
self._context.args = list(args)
|
||||||
self._context.group = group
|
self._context.group = group
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -37,7 +37,7 @@ try:
|
|||||||
import secrets
|
import secrets
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# New in Python 3.6
|
# New in Python 3.6
|
||||||
secrets = None
|
secrets = None # type: ignore
|
||||||
|
|
||||||
from PyQt5.QtCore import QUrlQuery, QUrl, qVersion
|
from PyQt5.QtCore import QUrlQuery, QUrl, qVersion
|
||||||
|
|
||||||
|
@ -670,7 +670,7 @@ class WebEngineAudio(browsertab.AbstractAudio):
|
|||||||
self._tab.url_changed.connect(self._on_url_changed)
|
self._tab.url_changed.connect(self._on_url_changed)
|
||||||
config.instance.changed.connect(self._on_config_changed)
|
config.instance.changed.connect(self._on_config_changed)
|
||||||
|
|
||||||
def set_muted(self, muted: bool, override: bool = False):
|
def set_muted(self, muted: bool, override: bool = False) -> None:
|
||||||
self._overridden = override
|
self._overridden = override
|
||||||
page = self._widget.page()
|
page = self._widget.page()
|
||||||
page.setAudioMuted(muted)
|
page.setAudioMuted(muted)
|
||||||
|
@ -240,7 +240,7 @@ class WebEnginePage(QWebEnginePage):
|
|||||||
def acceptNavigationRequest(self,
|
def acceptNavigationRequest(self,
|
||||||
url: QUrl,
|
url: QUrl,
|
||||||
typ: QWebEnginePage.NavigationType,
|
typ: QWebEnginePage.NavigationType,
|
||||||
is_main_frame: bool):
|
is_main_frame: bool) -> bool:
|
||||||
"""Override acceptNavigationRequest to forward it to the tab API."""
|
"""Override acceptNavigationRequest to forward it to the tab API."""
|
||||||
type_map = {
|
type_map = {
|
||||||
QWebEnginePage.NavigationTypeLinkClicked:
|
QWebEnginePage.NavigationTypeLinkClicked:
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
import collections
|
import collections
|
||||||
import html
|
import html
|
||||||
|
import typing # pylint: disable=unused-import
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
from PyQt5.QtCore import (pyqtSlot, pyqtSignal, QCoreApplication, QUrl,
|
from PyQt5.QtCore import (pyqtSlot, pyqtSignal, QCoreApplication, QUrl,
|
||||||
@ -28,6 +29,7 @@ from PyQt5.QtCore import (pyqtSlot, pyqtSignal, QCoreApplication, QUrl,
|
|||||||
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkReply, QSslSocket
|
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkReply, QSslSocket
|
||||||
|
|
||||||
from qutebrowser.config import config
|
from qutebrowser.config import config
|
||||||
|
from qutebrowser.mainwindow import prompt # pylint: disable=unused-import
|
||||||
from qutebrowser.utils import (message, log, usertypes, utils, objreg,
|
from qutebrowser.utils import (message, log, usertypes, utils, objreg,
|
||||||
urlutils, debug)
|
urlutils, debug)
|
||||||
from qutebrowser.browser import shared
|
from qutebrowser.browser import shared
|
||||||
@ -37,7 +39,7 @@ from qutebrowser.browser.webkit.network import (webkitqutescheme, networkreply,
|
|||||||
|
|
||||||
|
|
||||||
HOSTBLOCK_ERROR_STRING = '%HOSTBLOCK%'
|
HOSTBLOCK_ERROR_STRING = '%HOSTBLOCK%'
|
||||||
_proxy_auth_cache = {}
|
_proxy_auth_cache = {} # type: typing.Dict[ProxyId, prompt.AuthInfo]
|
||||||
|
|
||||||
|
|
||||||
@attr.s(frozen=True)
|
@attr.s(frozen=True)
|
||||||
@ -295,9 +297,9 @@ class NetworkManager(QNetworkAccessManager):
|
|||||||
"""Called when a proxy needs authentication."""
|
"""Called when a proxy needs authentication."""
|
||||||
proxy_id = ProxyId(proxy.type(), proxy.hostName(), proxy.port())
|
proxy_id = ProxyId(proxy.type(), proxy.hostName(), proxy.port())
|
||||||
if proxy_id in _proxy_auth_cache:
|
if proxy_id in _proxy_auth_cache:
|
||||||
user, password = _proxy_auth_cache[proxy_id]
|
authinfo = _proxy_auth_cache[proxy_id]
|
||||||
authenticator.setUser(user)
|
authenticator.setUser(authinfo.user)
|
||||||
authenticator.setPassword(password)
|
authenticator.setPassword(authinfo.password)
|
||||||
else:
|
else:
|
||||||
msg = '<b>{}</b> says:<br/>{}'.format(
|
msg = '<b>{}</b> says:<br/>{}'.format(
|
||||||
html.escape(proxy.hostName()),
|
html.escape(proxy.hostName()),
|
||||||
|
@ -641,7 +641,7 @@ class WebKitAudio(browsertab.AbstractAudio):
|
|||||||
|
|
||||||
"""Dummy handling of audio status for QtWebKit."""
|
"""Dummy handling of audio status for QtWebKit."""
|
||||||
|
|
||||||
def set_muted(self, muted: bool, override: bool = False):
|
def set_muted(self, muted: bool, override: bool = False) -> None:
|
||||||
raise browsertab.WebTabError('Muting is not supported on QtWebKit!')
|
raise browsertab.WebTabError('Muting is not supported on QtWebKit!')
|
||||||
|
|
||||||
def is_muted(self):
|
def is_muted(self):
|
||||||
|
@ -469,7 +469,7 @@ class BrowserPage(QWebPage):
|
|||||||
def acceptNavigationRequest(self,
|
def acceptNavigationRequest(self,
|
||||||
frame: QWebFrame,
|
frame: QWebFrame,
|
||||||
request: QNetworkRequest,
|
request: QNetworkRequest,
|
||||||
typ: QWebPage.NavigationType):
|
typ: QWebPage.NavigationType) -> bool:
|
||||||
"""Override acceptNavigationRequest to handle clicked links.
|
"""Override acceptNavigationRequest to handle clicked links.
|
||||||
|
|
||||||
Setting linkDelegationPolicy to DelegateAllLinks and using a slot bound
|
Setting linkDelegationPolicy to DelegateAllLinks and using a slot bound
|
||||||
|
@ -17,18 +17,15 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
"""Contains various command utils and a global command dict.
|
"""Contains various command utils and a global command dict."""
|
||||||
|
|
||||||
Module attributes:
|
|
||||||
cmd_dict: A mapping from command-strings to command objects.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
|
import typing # pylint: disable=unused-import
|
||||||
|
|
||||||
from qutebrowser.utils import qtutils, log
|
from qutebrowser.utils import qtutils, log
|
||||||
from qutebrowser.commands import command, cmdexc
|
from qutebrowser.commands import command, cmdexc
|
||||||
|
|
||||||
cmd_dict = {}
|
cmd_dict = {} # type: typing.Dict[str, command.Command]
|
||||||
|
|
||||||
|
|
||||||
def check_overflow(arg, ctype):
|
def check_overflow(arg, ctype):
|
||||||
|
@ -58,6 +58,9 @@ def _current_url(tabbed_browser):
|
|||||||
|
|
||||||
def replace_variables(win_id, arglist):
|
def replace_variables(win_id, arglist):
|
||||||
"""Utility function to replace variables like {url} in a list of args."""
|
"""Utility function to replace variables like {url} in a list of args."""
|
||||||
|
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
||||||
|
window=win_id)
|
||||||
|
|
||||||
variables = {
|
variables = {
|
||||||
'url': lambda: _current_url(tabbed_browser).toString(
|
'url': lambda: _current_url(tabbed_browser).toString(
|
||||||
QUrl.FullyEncoded | QUrl.RemovePassword),
|
QUrl.FullyEncoded | QUrl.RemovePassword),
|
||||||
@ -67,13 +70,13 @@ def replace_variables(win_id, arglist):
|
|||||||
'clipboard': utils.get_clipboard,
|
'clipboard': utils.get_clipboard,
|
||||||
'primary': lambda: utils.get_clipboard(selection=True),
|
'primary': lambda: utils.get_clipboard(selection=True),
|
||||||
}
|
}
|
||||||
|
|
||||||
for key in list(variables):
|
for key in list(variables):
|
||||||
modified_key = '{' + key + '}'
|
modified_key = '{' + key + '}'
|
||||||
variables[modified_key] = lambda x=modified_key: x
|
variables[modified_key] = lambda x=modified_key: x
|
||||||
|
|
||||||
values = {}
|
values = {}
|
||||||
args = []
|
args = []
|
||||||
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
|
||||||
window=win_id)
|
|
||||||
|
|
||||||
def repl_cb(matchobj):
|
def repl_cb(matchobj):
|
||||||
"""Return replacement for given match."""
|
"""Return replacement for given match."""
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
import copy
|
import copy
|
||||||
import contextlib
|
import contextlib
|
||||||
import functools
|
import functools
|
||||||
|
import typing
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject
|
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject
|
||||||
|
|
||||||
@ -30,11 +31,16 @@ from qutebrowser.utils import utils, log, jinja
|
|||||||
from qutebrowser.misc import objects
|
from qutebrowser.misc import objects
|
||||||
from qutebrowser.keyinput import keyutils
|
from qutebrowser.keyinput import keyutils
|
||||||
|
|
||||||
|
MYPY = False
|
||||||
|
if MYPY:
|
||||||
|
# pylint: disable=unused-import
|
||||||
|
from qutebrowser.config import configcache # pragma: no cover
|
||||||
|
|
||||||
# An easy way to access the config from other code via config.val.foo
|
# An easy way to access the config from other code via config.val.foo
|
||||||
val = None
|
val = typing.cast('ConfigContainer', None)
|
||||||
instance = None
|
instance = typing.cast('Config', None)
|
||||||
key_instance = None
|
key_instance = typing.cast('KeyConfig', None)
|
||||||
cache = None
|
cache = typing.cast('configcache.ConfigCache', None)
|
||||||
|
|
||||||
# Keeping track of all change filters to validate them later.
|
# Keeping track of all change filters to validate them later.
|
||||||
change_filters = []
|
change_filters = []
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
"""Implementation of a basic config cache."""
|
"""Implementation of a basic config cache."""
|
||||||
|
|
||||||
|
import typing
|
||||||
|
|
||||||
from qutebrowser.config import config
|
from qutebrowser.config import config
|
||||||
|
|
||||||
|
|
||||||
@ -36,14 +38,14 @@ class ConfigCache:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self._cache = {}
|
self._cache = {} # type: typing.Dict[str, typing.Any]
|
||||||
config.instance.changed.connect(self._on_config_changed)
|
config.instance.changed.connect(self._on_config_changed)
|
||||||
|
|
||||||
def _on_config_changed(self, attr: str) -> None:
|
def _on_config_changed(self, attr: str) -> None:
|
||||||
if attr in self._cache:
|
if attr in self._cache:
|
||||||
self._cache[attr] = config.instance.get(attr)
|
self._cache[attr] = config.instance.get(attr)
|
||||||
|
|
||||||
def __getitem__(self, attr: str):
|
def __getitem__(self, attr: str) -> typing.Any:
|
||||||
if attr not in self._cache:
|
if attr not in self._cache:
|
||||||
assert not config.instance.get_opt(attr).supports_pattern
|
assert not config.instance.get_opt(attr).supports_pattern
|
||||||
self._cache[attr] = config.instance.get(attr)
|
self._cache[attr] = config.instance.get(attr)
|
||||||
|
@ -52,6 +52,7 @@ import datetime
|
|||||||
import functools
|
import functools
|
||||||
import operator
|
import operator
|
||||||
import json
|
import json
|
||||||
|
import typing # pylint: disable=unused-import
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
import yaml
|
import yaml
|
||||||
@ -304,7 +305,7 @@ class MappingType(BaseType):
|
|||||||
MAPPING: The mapping to use.
|
MAPPING: The mapping to use.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
MAPPING = {}
|
MAPPING = {} # type: typing.Dict[str, typing.Any]
|
||||||
|
|
||||||
def __init__(self, none_ok=False, valid_values=None):
|
def __init__(self, none_ok=False, valid_values=None):
|
||||||
super().__init__(none_ok)
|
super().__init__(none_ok)
|
||||||
@ -576,7 +577,7 @@ class FlagList(List):
|
|||||||
the valid values of the setting.
|
the valid values of the setting.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
combinable_values = None
|
combinable_values = None # type: typing.Optional[typing.Iterable]
|
||||||
|
|
||||||
_show_valtype = False
|
_show_valtype = False
|
||||||
|
|
||||||
@ -1118,7 +1119,7 @@ class QtFont(Font):
|
|||||||
font.setWeight(weight_map[namedweight])
|
font.setWeight(weight_map[namedweight])
|
||||||
if weight:
|
if weight:
|
||||||
# based on qcssparser.cpp:setFontWeightFromValue
|
# based on qcssparser.cpp:setFontWeightFromValue
|
||||||
font.setWeight(min(int(weight) / 8, 99))
|
font.setWeight(min(int(weight) // 8, 99))
|
||||||
if size:
|
if size:
|
||||||
if size.lower().endswith('pt'):
|
if size.lower().endswith('pt'):
|
||||||
font.setPointSizeF(float(size[:-2]))
|
font.setPointSizeF(float(size[:-2]))
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
"""Bridge from QWeb(Engine)Settings to our own settings."""
|
"""Bridge from QWeb(Engine)Settings to our own settings."""
|
||||||
|
|
||||||
|
import typing # pylint: disable=unused-import
|
||||||
|
|
||||||
from PyQt5.QtGui import QFont
|
from PyQt5.QtGui import QFont
|
||||||
|
|
||||||
from qutebrowser.config import config, configutils
|
from qutebrowser.config import config, configutils
|
||||||
@ -44,10 +46,10 @@ class AbstractSettings:
|
|||||||
|
|
||||||
"""Abstract base class for settings set via QWeb(Engine)Settings."""
|
"""Abstract base class for settings set via QWeb(Engine)Settings."""
|
||||||
|
|
||||||
_ATTRIBUTES = None
|
_ATTRIBUTES = {} # type: typing.Dict[str, AttributeInfo]
|
||||||
_FONT_SIZES = None
|
_FONT_SIZES = {} # type: typing.Dict[str, typing.Any]
|
||||||
_FONT_FAMILIES = None
|
_FONT_FAMILIES = {} # type: typing.Dict[str, typing.Any]
|
||||||
_FONT_TO_QFONT = None
|
_FONT_TO_QFONT = {} # type: typing.Dict[typing.Any, QFont.StyleHint]
|
||||||
|
|
||||||
def __init__(self, settings):
|
def __init__(self, settings):
|
||||||
self._settings = settings
|
self._settings = settings
|
||||||
|
@ -391,7 +391,8 @@ class PromptContainer(QWidget):
|
|||||||
|
|
||||||
@cmdutils.register(instance='prompt-container', scope='window',
|
@cmdutils.register(instance='prompt-container', scope='window',
|
||||||
modes=[usertypes.KeyMode.prompt], maxsplit=0)
|
modes=[usertypes.KeyMode.prompt], maxsplit=0)
|
||||||
def prompt_open_download(self, cmdline: str = None, pdfjs=False):
|
def prompt_open_download(self, cmdline: str = None,
|
||||||
|
pdfjs: bool = False) -> None:
|
||||||
"""Immediately open a download.
|
"""Immediately open a download.
|
||||||
|
|
||||||
If no specific command is given, this will use the system's default
|
If no specific command is given, this will use the system's default
|
||||||
|
@ -145,7 +145,7 @@ class StatusBar(QWidget):
|
|||||||
resized = pyqtSignal('QRect')
|
resized = pyqtSignal('QRect')
|
||||||
moved = pyqtSignal('QPoint')
|
moved = pyqtSignal('QPoint')
|
||||||
_severity = None
|
_severity = None
|
||||||
_color_flags = []
|
_color_flags = None
|
||||||
|
|
||||||
STYLESHEET = _generate_stylesheet()
|
STYLESHEET = _generate_stylesheet()
|
||||||
|
|
||||||
|
@ -37,8 +37,11 @@ from qutebrowser.misc import objects
|
|||||||
from qutebrowser.browser import browsertab
|
from qutebrowser.browser import browsertab
|
||||||
|
|
||||||
|
|
||||||
PixelMetrics = enum.IntEnum('PixelMetrics', ['icon_padding'],
|
class PixelMetrics(enum.IntEnum):
|
||||||
start=QStyle.PM_CustomBase)
|
|
||||||
|
"""Custom PixelMetrics attributes."""
|
||||||
|
|
||||||
|
icon_padding = QStyle.PM_CustomBase
|
||||||
|
|
||||||
|
|
||||||
class TabWidget(QTabWidget):
|
class TabWidget(QTabWidget):
|
||||||
@ -339,7 +342,7 @@ class TabWidget(QTabWidget):
|
|||||||
qtutils.ensure_valid(url)
|
qtutils.ensure_valid(url)
|
||||||
return url
|
return url
|
||||||
|
|
||||||
def update_tab_favicon(self, tab: QWidget):
|
def update_tab_favicon(self, tab: QWidget) -> None:
|
||||||
"""Update favicon of the given tab."""
|
"""Update favicon of the given tab."""
|
||||||
idx = self.indexOf(tab)
|
idx = self.indexOf(tab)
|
||||||
|
|
||||||
@ -397,7 +400,7 @@ class TabBar(QTabBar):
|
|||||||
return self.parent().currentWidget()
|
return self.parent().currentWidget()
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def _on_config_changed(self, option: str):
|
def _on_config_changed(self, option: str) -> None:
|
||||||
if option == 'fonts.tabs':
|
if option == 'fonts.tabs':
|
||||||
self._set_font()
|
self._set_font()
|
||||||
elif option == 'tabs.favicons.scale':
|
elif option == 'tabs.favicons.scale':
|
||||||
@ -540,7 +543,7 @@ class TabBar(QTabBar):
|
|||||||
return
|
return
|
||||||
super().mousePressEvent(e)
|
super().mousePressEvent(e)
|
||||||
|
|
||||||
def minimumTabSizeHint(self, index, ellipsis: bool = True) -> QSize:
|
def minimumTabSizeHint(self, index: int, ellipsis: bool = True) -> QSize:
|
||||||
"""Set the minimum tab size to indicator/icon/... text.
|
"""Set the minimum tab size to indicator/icon/... text.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -620,7 +623,7 @@ class TabBar(QTabBar):
|
|||||||
return False
|
return False
|
||||||
return widget.data.pinned
|
return widget.data.pinned
|
||||||
|
|
||||||
def tabSizeHint(self, index: int):
|
def tabSizeHint(self, index: int) -> QSize:
|
||||||
"""Override tabSizeHint to customize qb's tab size.
|
"""Override tabSizeHint to customize qb's tab size.
|
||||||
|
|
||||||
https://wiki.python.org/moin/PyQt/Customising%20tab%20bars
|
https://wiki.python.org/moin/PyQt/Customising%20tab%20bars
|
||||||
|
@ -38,10 +38,14 @@ from qutebrowser.utils import usertypes, objreg, version, qtutils, log, utils
|
|||||||
from qutebrowser.misc import objects, msgbox
|
from qutebrowser.misc import objects, msgbox
|
||||||
|
|
||||||
|
|
||||||
_Result = enum.IntEnum(
|
class _Result(enum.IntEnum):
|
||||||
'_Result',
|
|
||||||
['quit', 'restart', 'restart_webkit', 'restart_webengine'],
|
"""The result code returned by the backend problem dialog."""
|
||||||
start=QDialog.Accepted + 1)
|
|
||||||
|
quit = QDialog.Accepted + 1
|
||||||
|
restart = QDialog.Accepted + 2
|
||||||
|
restart_webkit = QDialog.Accepted + 3
|
||||||
|
restart_webengine = QDialog.Accepted + 4
|
||||||
|
|
||||||
|
|
||||||
@attr.s
|
@attr.s
|
||||||
|
@ -30,12 +30,12 @@ try:
|
|||||||
except ImportError: # pragma: no cover
|
except ImportError: # pragma: no cover
|
||||||
try:
|
try:
|
||||||
# Python2
|
# Python2
|
||||||
from Tkinter import Tk
|
from Tkinter import Tk # type: ignore
|
||||||
import tkMessageBox as messagebox
|
import tkMessageBox as messagebox # type: ignore
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# Some Python without Tk
|
# Some Python without Tk
|
||||||
Tk = None
|
Tk = None # type: ignore
|
||||||
messagebox = None
|
messagebox = None # type: ignore
|
||||||
|
|
||||||
|
|
||||||
# First we check the version of Python. This code should run fine with python2
|
# First we check the version of Python. This code should run fine with python2
|
||||||
|
@ -42,8 +42,12 @@ from qutebrowser.misc import (miscwidgets, autoupdate, msgbox, httpclient,
|
|||||||
from qutebrowser.config import config, configfiles
|
from qutebrowser.config import config, configfiles
|
||||||
|
|
||||||
|
|
||||||
Result = enum.IntEnum('Result', ['restore', 'no_restore'],
|
class Result(enum.IntEnum):
|
||||||
start=QDialog.Accepted + 1)
|
|
||||||
|
"""The result code returned by the crash dialog."""
|
||||||
|
|
||||||
|
restore = QDialog.Accepted + 1
|
||||||
|
no_restore = QDialog.Accepted + 2
|
||||||
|
|
||||||
|
|
||||||
def parse_fatal_stacktrace(text):
|
def parse_fatal_stacktrace(text):
|
||||||
|
@ -38,7 +38,7 @@ import datetime
|
|||||||
try:
|
try:
|
||||||
import tkinter
|
import tkinter
|
||||||
except ImportError:
|
except ImportError:
|
||||||
tkinter = None
|
tkinter = None # type: ignore
|
||||||
|
|
||||||
# NOTE: No qutebrowser or PyQt import should be done here, as some early
|
# NOTE: No qutebrowser or PyQt import should be done here, as some early
|
||||||
# initialization needs to take place before that!
|
# initialization needs to take place before that!
|
||||||
|
@ -23,6 +23,7 @@ import os
|
|||||||
import os.path
|
import os.path
|
||||||
import itertools
|
import itertools
|
||||||
import urllib
|
import urllib
|
||||||
|
import typing
|
||||||
|
|
||||||
from PyQt5.QtCore import QUrl, QObject, QPoint, QTimer
|
from PyQt5.QtCore import QUrl, QObject, QPoint, QTimer
|
||||||
from PyQt5.QtWidgets import QApplication
|
from PyQt5.QtWidgets import QApplication
|
||||||
@ -37,7 +38,14 @@ from qutebrowser.mainwindow import mainwindow
|
|||||||
from qutebrowser.qt import sip
|
from qutebrowser.qt import sip
|
||||||
|
|
||||||
|
|
||||||
default = object() # Sentinel value
|
class Sentinel:
|
||||||
|
|
||||||
|
"""Sentinel value for default argument."""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
default = Sentinel()
|
||||||
|
|
||||||
|
|
||||||
def init(parent=None):
|
def init(parent=None):
|
||||||
@ -109,7 +117,7 @@ class SessionManager(QObject):
|
|||||||
|
|
||||||
def __init__(self, base_path, parent=None):
|
def __init__(self, base_path, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._current = None
|
self._current = None # type: typing.Optional[str]
|
||||||
self._base_path = base_path
|
self._base_path = base_path
|
||||||
self._last_window_session = None
|
self._last_window_session = None
|
||||||
self.did_load = False
|
self.did_load = False
|
||||||
@ -504,9 +512,13 @@ class SessionManager(QObject):
|
|||||||
@cmdutils.argument('name', completion=miscmodels.session)
|
@cmdutils.argument('name', completion=miscmodels.session)
|
||||||
@cmdutils.argument('win_id', win_id=True)
|
@cmdutils.argument('win_id', win_id=True)
|
||||||
@cmdutils.argument('with_private', flag='p')
|
@cmdutils.argument('with_private', flag='p')
|
||||||
def session_save(self, name: str = default, current=False, quiet=False,
|
def session_save(self, name: typing.Union[str, Sentinel] = default,
|
||||||
force=False, only_active_window=False, with_private=False,
|
current: bool = False,
|
||||||
win_id=None):
|
quiet: bool = False,
|
||||||
|
force: bool = False,
|
||||||
|
only_active_window: bool = False,
|
||||||
|
with_private: bool = False,
|
||||||
|
win_id: int = None) -> None:
|
||||||
"""Save a session.
|
"""Save a session.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -518,7 +530,9 @@ class SessionManager(QObject):
|
|||||||
only_active_window: Saves only tabs of the currently active window.
|
only_active_window: Saves only tabs of the currently active window.
|
||||||
with_private: Include private windows.
|
with_private: Include private windows.
|
||||||
"""
|
"""
|
||||||
if name is not default and name.startswith('_') and not force:
|
if (not isinstance(name, Sentinel) and
|
||||||
|
name.startswith('_') and
|
||||||
|
not force):
|
||||||
raise cmdexc.CommandError("{} is an internal session, use --force "
|
raise cmdexc.CommandError("{} is an internal session, use --force "
|
||||||
"to save anyways.".format(name))
|
"to save anyways.".format(name))
|
||||||
if current:
|
if current:
|
||||||
|
@ -44,7 +44,7 @@ from qutebrowser.qt import sip
|
|||||||
|
|
||||||
@cmdutils.register(maxsplit=1, no_cmd_split=True, no_replace_variables=True)
|
@cmdutils.register(maxsplit=1, no_cmd_split=True, no_replace_variables=True)
|
||||||
@cmdutils.argument('win_id', win_id=True)
|
@cmdutils.argument('win_id', win_id=True)
|
||||||
def later(ms: int, command, win_id):
|
def later(ms: int, command: str, win_id: int) -> None:
|
||||||
"""Execute a command after some time.
|
"""Execute a command after some time.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -75,7 +75,7 @@ def later(ms: int, command, win_id):
|
|||||||
@cmdutils.register(maxsplit=1, no_cmd_split=True, no_replace_variables=True)
|
@cmdutils.register(maxsplit=1, no_cmd_split=True, no_replace_variables=True)
|
||||||
@cmdutils.argument('win_id', win_id=True)
|
@cmdutils.argument('win_id', win_id=True)
|
||||||
@cmdutils.argument('count', count=True)
|
@cmdutils.argument('count', count=True)
|
||||||
def repeat(times: int, command, win_id, count=None):
|
def repeat(times: int, command: str, win_id: int, count: int = None) -> None:
|
||||||
"""Repeat a given command.
|
"""Repeat a given command.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -96,7 +96,8 @@ def repeat(times: int, command, win_id, count=None):
|
|||||||
@cmdutils.register(maxsplit=1, no_cmd_split=True, no_replace_variables=True)
|
@cmdutils.register(maxsplit=1, no_cmd_split=True, no_replace_variables=True)
|
||||||
@cmdutils.argument('win_id', win_id=True)
|
@cmdutils.argument('win_id', win_id=True)
|
||||||
@cmdutils.argument('count', count=True)
|
@cmdutils.argument('count', count=True)
|
||||||
def run_with_count(count_arg: int, command, win_id, count=1):
|
def run_with_count(count_arg: int, command: str, win_id: int,
|
||||||
|
count: int = 1) -> None:
|
||||||
"""Run a command with the given count.
|
"""Run a command with the given count.
|
||||||
|
|
||||||
If run_with_count itself is run with a count, it multiplies count_arg.
|
If run_with_count itself is run with a count, it multiplies count_arg.
|
||||||
@ -303,7 +304,7 @@ def repeat_command(win_id, count=None):
|
|||||||
|
|
||||||
|
|
||||||
@cmdutils.register(debug=True, name='debug-log-capacity')
|
@cmdutils.register(debug=True, name='debug-log-capacity')
|
||||||
def log_capacity(capacity: int):
|
def log_capacity(capacity: int) -> None:
|
||||||
"""Change the number of log lines to be stored in RAM.
|
"""Change the number of log lines to be stored in RAM.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -312,6 +313,7 @@ def log_capacity(capacity: int):
|
|||||||
if capacity < 0:
|
if capacity < 0:
|
||||||
raise cmdexc.CommandError("Can't set a negative log capacity!")
|
raise cmdexc.CommandError("Can't set a negative log capacity!")
|
||||||
else:
|
else:
|
||||||
|
assert log.ram_handler is not None
|
||||||
log.ram_handler.change_log_capacity(capacity)
|
log.ram_handler.change_log_capacity(capacity)
|
||||||
|
|
||||||
|
|
||||||
@ -319,18 +321,19 @@ def log_capacity(capacity: int):
|
|||||||
@cmdutils.argument('level', choices=sorted(
|
@cmdutils.argument('level', choices=sorted(
|
||||||
(level.lower() for level in log.LOG_LEVELS),
|
(level.lower() for level in log.LOG_LEVELS),
|
||||||
key=lambda e: log.LOG_LEVELS[e.upper()]))
|
key=lambda e: log.LOG_LEVELS[e.upper()]))
|
||||||
def debug_log_level(level: str):
|
def debug_log_level(level: str) -> None:
|
||||||
"""Change the log level for console logging.
|
"""Change the log level for console logging.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
level: The log level to set.
|
level: The log level to set.
|
||||||
"""
|
"""
|
||||||
log.change_console_formatter(log.LOG_LEVELS[level.upper()])
|
log.change_console_formatter(log.LOG_LEVELS[level.upper()])
|
||||||
|
assert log.console_handler is not None
|
||||||
log.console_handler.setLevel(log.LOG_LEVELS[level.upper()])
|
log.console_handler.setLevel(log.LOG_LEVELS[level.upper()])
|
||||||
|
|
||||||
|
|
||||||
@cmdutils.register(debug=True)
|
@cmdutils.register(debug=True)
|
||||||
def debug_log_filter(filters: str):
|
def debug_log_filter(filters: str) -> None:
|
||||||
"""Change the log filter for console logging.
|
"""Change the log filter for console logging.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -25,4 +25,4 @@
|
|||||||
try:
|
try:
|
||||||
from PyQt5 import sip
|
from PyQt5 import sip
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import sip
|
import sip # type: ignore
|
||||||
|
@ -76,12 +76,13 @@ LOG_COLORS = {
|
|||||||
|
|
||||||
# We first monkey-patch logging to support our VDEBUG level before getting the
|
# We first monkey-patch logging to support our VDEBUG level before getting the
|
||||||
# loggers. Based on http://stackoverflow.com/a/13638084
|
# loggers. Based on http://stackoverflow.com/a/13638084
|
||||||
|
# mypy doesn't know about this, so we need to ignore it.
|
||||||
VDEBUG_LEVEL = 9
|
VDEBUG_LEVEL = 9
|
||||||
logging.addLevelName(VDEBUG_LEVEL, 'VDEBUG')
|
logging.addLevelName(VDEBUG_LEVEL, 'VDEBUG')
|
||||||
logging.VDEBUG = VDEBUG_LEVEL
|
logging.VDEBUG = VDEBUG_LEVEL # type: ignore
|
||||||
|
|
||||||
LOG_LEVELS = {
|
LOG_LEVELS = {
|
||||||
'VDEBUG': logging.VDEBUG,
|
'VDEBUG': logging.VDEBUG, # type: ignore
|
||||||
'DEBUG': logging.DEBUG,
|
'DEBUG': logging.DEBUG,
|
||||||
'INFO': logging.INFO,
|
'INFO': logging.INFO,
|
||||||
'WARNING': logging.WARNING,
|
'WARNING': logging.WARNING,
|
||||||
@ -89,17 +90,6 @@ LOG_LEVELS = {
|
|||||||
'CRITICAL': logging.CRITICAL,
|
'CRITICAL': logging.CRITICAL,
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER_NAMES = [
|
|
||||||
'statusbar', 'completion', 'init', 'url',
|
|
||||||
'destroy', 'modes', 'webview', 'misc',
|
|
||||||
'mouse', 'procs', 'hints', 'keyboard',
|
|
||||||
'commands', 'signals', 'downloads',
|
|
||||||
'js', 'qt', 'rfc6266', 'ipc', 'shlexer',
|
|
||||||
'save', 'message', 'config', 'sessions',
|
|
||||||
'webelem', 'prompt', 'network', 'sql',
|
|
||||||
'greasemonkey'
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def vdebug(self, msg, *args, **kwargs):
|
def vdebug(self, msg, *args, **kwargs):
|
||||||
"""Log with a VDEBUG level.
|
"""Log with a VDEBUG level.
|
||||||
@ -114,7 +104,7 @@ def vdebug(self, msg, *args, **kwargs):
|
|||||||
# pylint: enable=protected-access
|
# pylint: enable=protected-access
|
||||||
|
|
||||||
|
|
||||||
logging.Logger.vdebug = vdebug
|
logging.Logger.vdebug = vdebug # type: ignore
|
||||||
|
|
||||||
|
|
||||||
# The different loggers used.
|
# The different loggers used.
|
||||||
@ -148,6 +138,17 @@ network = logging.getLogger('network')
|
|||||||
sql = logging.getLogger('sql')
|
sql = logging.getLogger('sql')
|
||||||
greasemonkey = logging.getLogger('greasemonkey')
|
greasemonkey = logging.getLogger('greasemonkey')
|
||||||
|
|
||||||
|
LOGGER_NAMES = [
|
||||||
|
'statusbar', 'completion', 'init', 'url',
|
||||||
|
'destroy', 'modes', 'webview', 'misc',
|
||||||
|
'mouse', 'procs', 'hints', 'keyboard',
|
||||||
|
'commands', 'signals', 'downloads',
|
||||||
|
'js', 'qt', 'rfc6266', 'ipc', 'shlexer',
|
||||||
|
'save', 'message', 'config', 'sessions',
|
||||||
|
'webelem', 'prompt', 'network', 'sql',
|
||||||
|
'greasemonkey'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
ram_handler = None
|
ram_handler = None
|
||||||
console_handler = None
|
console_handler = None
|
||||||
@ -467,7 +468,7 @@ def qt_message_handler(msg_type, context, msg):
|
|||||||
stack = ''.join(traceback.format_stack())
|
stack = ''.join(traceback.format_stack())
|
||||||
else:
|
else:
|
||||||
stack = None
|
stack = None
|
||||||
record = qt.makeRecord(name, level, context.file, context.line, msg, None,
|
record = qt.makeRecord(name, level, context.file, context.line, msg, (),
|
||||||
None, func, sinfo=stack)
|
None, func, sinfo=stack)
|
||||||
qt.handle(record)
|
qt.handle(record)
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ from PyQt5.QtCore import (qVersion, QEventLoop, QDataStream, QByteArray,
|
|||||||
try:
|
try:
|
||||||
from PyQt5.QtWebKit import qWebKitVersion
|
from PyQt5.QtWebKit import qWebKitVersion
|
||||||
except ImportError: # pragma: no cover
|
except ImportError: # pragma: no cover
|
||||||
qWebKitVersion = None
|
qWebKitVersion = None # type: ignore
|
||||||
|
|
||||||
|
|
||||||
MAXVALS = {
|
MAXVALS = {
|
||||||
|
@ -221,10 +221,15 @@ KeyMode = enum.Enum('KeyMode', ['normal', 'hint', 'command', 'yesno', 'prompt',
|
|||||||
'jump_mark', 'record_macro', 'run_macro'])
|
'jump_mark', 'record_macro', 'run_macro'])
|
||||||
|
|
||||||
|
|
||||||
# Exit statuses for errors. Needs to be an int for sys.exit.
|
class Exit(enum.IntEnum):
|
||||||
Exit = enum.IntEnum('Exit', ['ok', 'reserved', 'exception', 'err_ipc',
|
|
||||||
'err_init', 'err_config', 'err_key_config'],
|
"""Exit statuses for errors. Needs to be an int for sys.exit."""
|
||||||
start=0)
|
|
||||||
|
ok = 0
|
||||||
|
reserved = 1
|
||||||
|
exception = 2
|
||||||
|
err_ipc = 3
|
||||||
|
err_init = 4
|
||||||
|
|
||||||
|
|
||||||
# Load status of a tab
|
# Load status of a tab
|
||||||
|
@ -41,7 +41,8 @@ from PyQt5.QtWidgets import QApplication
|
|||||||
import pkg_resources
|
import pkg_resources
|
||||||
import yaml
|
import yaml
|
||||||
try:
|
try:
|
||||||
from yaml import CSafeLoader as YamlLoader, CSafeDumper as YamlDumper
|
from yaml import (CSafeLoader as YamlLoader, # type: ignore
|
||||||
|
CSafeDumper as YamlDumper)
|
||||||
YAML_C_EXT = True
|
YAML_C_EXT = True
|
||||||
except ImportError: # pragma: no cover
|
except ImportError: # pragma: no cover
|
||||||
from yaml import SafeLoader as YamlLoader, SafeDumper as YamlDumper
|
from yaml import SafeLoader as YamlLoader, SafeDumper as YamlDumper
|
||||||
|
@ -42,12 +42,12 @@ from PyQt5.QtWidgets import QApplication
|
|||||||
try:
|
try:
|
||||||
from PyQt5.QtWebKit import qWebKitVersion
|
from PyQt5.QtWebKit import qWebKitVersion
|
||||||
except ImportError: # pragma: no cover
|
except ImportError: # pragma: no cover
|
||||||
qWebKitVersion = None
|
qWebKitVersion = None # type: ignore
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from PyQt5.QtWebEngineWidgets import QWebEngineProfile
|
from PyQt5.QtWebEngineWidgets import QWebEngineProfile
|
||||||
except ImportError: # pragma: no cover
|
except ImportError: # pragma: no cover
|
||||||
QWebEngineProfile = None
|
QWebEngineProfile = None # type: ignore
|
||||||
|
|
||||||
import qutebrowser
|
import qutebrowser
|
||||||
from qutebrowser.utils import log, utils, standarddir, usertypes, message
|
from qutebrowser.utils import log, utils, standarddir, usertypes, message
|
||||||
|
@ -84,6 +84,7 @@ def whitelist_generator(): # noqa
|
|||||||
yield 'qutebrowser.utils.log.QtWarningFilter.filter'
|
yield 'qutebrowser.utils.log.QtWarningFilter.filter'
|
||||||
yield 'qutebrowser.browser.pdfjs.is_available'
|
yield 'qutebrowser.browser.pdfjs.is_available'
|
||||||
yield 'qutebrowser.misc.guiprocess.spawn_output'
|
yield 'qutebrowser.misc.guiprocess.spawn_output'
|
||||||
|
yield 'qutebrowser.utils.usertypes.ExitStatus.reserved'
|
||||||
yield 'QEvent.posted'
|
yield 'QEvent.posted'
|
||||||
yield 'log_stack' # from message.py
|
yield 'log_stack' # from message.py
|
||||||
yield 'propagate' # logging.getLogger('...).propagate = False
|
yield 'propagate' # logging.getLogger('...).propagate = False
|
||||||
|
11
tox.ini
11
tox.ini
@ -188,3 +188,14 @@ deps =
|
|||||||
whitelist_externals = eslint
|
whitelist_externals = eslint
|
||||||
changedir = {toxinidir}/qutebrowser/javascript
|
changedir = {toxinidir}/qutebrowser/javascript
|
||||||
commands = eslint --color --report-unused-disable-directives .
|
commands = eslint --color --report-unused-disable-directives .
|
||||||
|
|
||||||
|
[testenv:mypy]
|
||||||
|
basepython = {env:PYTHON:python3}
|
||||||
|
passenv =
|
||||||
|
deps =
|
||||||
|
-r{toxinidir}/requirements.txt
|
||||||
|
-r{toxinidir}/misc/requirements/requirements-optional.txt
|
||||||
|
-r{toxinidir}/misc/requirements/requirements-pyqt.txt
|
||||||
|
-r{toxinidir}/misc/requirements/requirements-mypy.txt
|
||||||
|
commands =
|
||||||
|
{envpython} -m mypy qutebrowser {posargs}
|
||||||
|
Loading…
Reference in New Issue
Block a user