summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <me@the-compiler.org>2023-06-29 23:06:54 +0200
committerFlorian Bruhin <me@the-compiler.org>2023-06-29 23:06:54 +0200
commit69e2bbd7668ff4a3b3e64e3a4a4d584be8ed6f71 (patch)
tree0ae2225f521f65c8873950742c13a4dab951f8e5
parent42f0ee36e3f789207fe3e2cc76efe95194e067db (diff)
downloadqutebrowser-69e2bbd7668ff4a3b3e64e3a4a4d584be8ed6f71.tar.gz
qutebrowser-69e2bbd7668ff4a3b3e64e3a4a4d584be8ed6f71.zip
qt6 mypy: Fix PyQt5 QUrl issues with a more clever approach
-rw-r--r--qutebrowser/browser/browsertab.py3
-rw-r--r--qutebrowser/browser/commands.py5
-rw-r--r--qutebrowser/browser/hints.py13
-rw-r--r--qutebrowser/browser/pdfjs.py6
-rw-r--r--qutebrowser/browser/shared.py6
-rw-r--r--qutebrowser/browser/webengine/notification.py6
-rw-r--r--qutebrowser/browser/webengine/webenginetab.py4
-rw-r--r--qutebrowser/browser/webkit/webview.py5
-rw-r--r--qutebrowser/keyinput/keyutils.py3
-rw-r--r--qutebrowser/utils/jinja.py2
-rw-r--r--qutebrowser/utils/urlutils.py41
11 files changed, 63 insertions, 31 deletions
diff --git a/qutebrowser/browser/browsertab.py b/qutebrowser/browser/browsertab.py
index 0fbd15c21..ea4cf8004 100644
--- a/qutebrowser/browser/browsertab.py
+++ b/qutebrowser/browser/browsertab.py
@@ -1331,8 +1331,7 @@ class AbstractTab(QWidget):
def __repr__(self) -> str:
try:
qurl = self.url()
- as_unicode = QUrl.ComponentFormattingOption.EncodeUnicode
- url = qurl.toDisplayString(as_unicode)
+ url = qurl.toDisplayString(urlutils.FormatOption.ENCODE_UNICODE)
except (AttributeError, RuntimeError) as exc:
url = '<{}>'.format(exc.__class__.__name__)
else:
diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py
index 750f28c9c..0f2496e0d 100644
--- a/qutebrowser/browser/commands.py
+++ b/qutebrowser/browser/commands.py
@@ -718,9 +718,10 @@ class CommandDispatcher:
assert what in ['url', 'pretty-url'], what
if what == 'pretty-url':
- flags = QUrl.UrlFormattingOption.RemovePassword | QUrl.ComponentFormattingOption.DecodeReserved
+ flags = urlutils.FormatOption.DECODE_RESERVED
else:
- flags = QUrl.UrlFormattingOption.RemovePassword | QUrl.ComponentFormattingOption.FullyEncoded
+ flags = urlutils.FormatOption.ENCODED
+ flags |= urlutils.FormatOption.REMOVE_PASSWORD
url = QUrl(self._current_url())
url_query = QUrlQuery()
diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py
index 5d7862e75..6e028baa4 100644
--- a/qutebrowser/browser/hints.py
+++ b/qutebrowser/browser/hints.py
@@ -38,7 +38,7 @@ from qutebrowser.keyinput import modeman, modeparsers, basekeyparser
from qutebrowser.browser import webelem, history
from qutebrowser.commands import runners
from qutebrowser.api import cmdutils
-from qutebrowser.utils import usertypes, log, qtutils, message, objreg, utils
+from qutebrowser.utils import usertypes, log, qtutils, message, objreg, utils, urlutils
if TYPE_CHECKING:
from qutebrowser.browser import browsertab
@@ -252,9 +252,9 @@ class HintActions:
sel = (context.target == Target.yank_primary and
utils.supports_selection())
- flags = QUrl.ComponentFormattingOption.FullyEncoded | QUrl.UrlFormattingOption.RemovePassword
+ flags = urlutils.FormatOption.ENCODED | urlutils.FormatOption.REMOVE_PASSWORD
if url.scheme() == 'mailto':
- flags |= QUrl.UrlFormattingOption.RemoveScheme
+ flags |= urlutils.FormatOption.REMOVE_SCHEME
urlstr = url.toString(flags)
new_content = urlstr
@@ -276,15 +276,14 @@ class HintActions:
def run_cmd(self, url: QUrl, context: HintContext) -> None:
"""Run the command based on a hint URL."""
- urlstr = url.toString(QUrl.ComponentFormattingOption.FullyEncoded)
+ urlstr = url.toString(urlutils.FormatOption.ENCODED)
args = context.get_args(urlstr)
commandrunner = runners.CommandRunner(self._win_id)
commandrunner.run_safely(' '.join(args))
def preset_cmd_text(self, url: QUrl, context: HintContext) -> None:
"""Preset a commandline text based on a hint URL."""
- flags = QUrl.ComponentFormattingOption.FullyEncoded
- urlstr = url.toDisplayString(flags)
+ urlstr = url.toDisplayString(urlutils.FormatOption.ENCODED)
args = context.get_args(urlstr)
text = ' '.join(args)
if text[0] not in modeparsers.STARTCHARS:
@@ -325,7 +324,7 @@ class HintActions:
cmd = context.args[0]
args = context.args[1:]
- flags = QUrl.ComponentFormattingOption.FullyEncoded
+ flags = urlutils.FormatOption.ENCODED
env = {
'QUTE_MODE': 'hints',
diff --git a/qutebrowser/browser/pdfjs.py b/qutebrowser/browser/pdfjs.py
index 53387d634..fe6851a53 100644
--- a/qutebrowser/browser/pdfjs.py
+++ b/qutebrowser/browser/pdfjs.py
@@ -24,7 +24,7 @@ import os
from qutebrowser.qt.core import QUrl, QUrlQuery
-from qutebrowser.utils import resources, javascript, jinja, standarddir, log
+from qutebrowser.utils import resources, javascript, jinja, standarddir, log, urlutils
from qutebrowser.config import config
@@ -95,7 +95,7 @@ def _generate_pdfjs_script(filename):
url_query.addQueryItem('filename', filename)
url.setQuery(url_query)
- js_url = javascript.to_js(url.toString(QUrl.ComponentFormattingOption.FullyEncoded))
+ js_url = javascript.to_js(url.toString(urlutils.FormatOption.ENCODED))
return jinja.js_environment.from_string("""
document.addEventListener("DOMContentLoaded", function() {
@@ -244,7 +244,7 @@ def get_main_url(filename: str, original_url: QUrl) -> QUrl:
query = QUrlQuery()
query.addQueryItem('filename', filename) # read from our JS
query.addQueryItem('file', '') # to avoid pdfjs opening the default PDF
- urlstr = original_url.toString(QUrl.ComponentFormattingOption.FullyEncoded)
+ urlstr = original_url.toString(urlutils.FormatOption.ENCODED)
query.addQueryItem('source', urlstr)
url.setQuery(query)
return url
diff --git a/qutebrowser/browser/shared.py b/qutebrowser/browser/shared.py
index 562442b5a..13080ece6 100644
--- a/qutebrowser/browser/shared.py
+++ b/qutebrowser/browser/shared.py
@@ -31,7 +31,7 @@ from qutebrowser.qt.core import QUrl, pyqtBoundSignal
from qutebrowser.config import config
from qutebrowser.utils import (usertypes, message, log, objreg, jinja, utils,
- qtutils, version)
+ qtutils, version, urlutils)
from qutebrowser.mainwindow import mainwindow
from qutebrowser.misc import guiprocess, objects
@@ -229,7 +229,7 @@ def handle_certificate_error(
# scheme might not match.
is_resource = (
first_party_url.isValid() and
- not request_url.matches(first_party_url, QUrl.UrlFormattingOption.RemoveScheme))
+ not request_url.matches(first_party_url, urlutils.FormatOption.REMOVE_SCHEME))
if conf == 'ask' or conf == 'ask-block-thirdparty' and not is_resource:
err_template = jinja.environment.from_string("""
@@ -259,7 +259,7 @@ def handle_certificate_error(
error=error,
)
urlstr = request_url.toString(
- QUrl.UrlFormattingOption.RemovePassword | QUrl.ComponentFormattingOption.FullyEncoded)
+ urlutils.FormatOption.REMOVE_PASSWORD | urlutils.FormatOption.ENCODED)
title = "Certificate error"
try:
diff --git a/qutebrowser/browser/webengine/notification.py b/qutebrowser/browser/webengine/notification.py
index 76ba6b886..2912c8b3e 100644
--- a/qutebrowser/browser/webengine/notification.py
+++ b/qutebrowser/browser/webengine/notification.py
@@ -66,7 +66,7 @@ if TYPE_CHECKING:
from qutebrowser.config import config
from qutebrowser.misc import objects
from qutebrowser.utils import (
- qtutils, log, utils, debug, message, objreg, resources,
+ qtutils, log, utils, debug, message, objreg, resources, urlutils
)
from qutebrowser.qt import sip
@@ -1179,9 +1179,7 @@ class DBusNotificationAdapter(AbstractNotificationAdapter):
if self._capabilities.kde_origin_name or not is_useful_origin:
prefix = None
elif self._capabilities.body_markup and self._capabilities.body_hyperlinks:
- href = html.escape(
- origin_url.toString(QUrl.ComponentFormattingOption.FullyEncoded)
- )
+ href = html.escape(origin_url.toString(urlutils.FormatOption.ENCODED))
text = html.escape(urlstr, quote=False)
prefix = f'<a href="{href}">{text}</a>'
elif self._capabilities.body_markup:
diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py
index f1e3c1e8e..6080a974d 100644
--- a/qutebrowser/browser/webengine/webenginetab.py
+++ b/qutebrowser/browser/webengine/webenginetab.py
@@ -39,7 +39,7 @@ from qutebrowser.browser.webengine import (webview, webengineelem, tabhistory,
webengineinspector)
from qutebrowser.utils import (usertypes, qtutils, log, javascript, utils,
- resources, message, jinja, debug, version)
+ resources, message, jinja, debug, version, urlutils)
from qutebrowser.qt import sip, machinery
from qutebrowser.misc import objects, miscwidgets
@@ -1437,7 +1437,7 @@ class WebEngineTab(browsertab.AbstractTab):
title = self.title()
title_url = QUrl(url)
title_url.setScheme('')
- title_url_str = title_url.toDisplayString(QUrl.UrlFormattingOption.RemoveScheme)
+ title_url_str = title_url.toDisplayString(urlutils.FormatOption.REMOVE_SCHEME)
if title == title_url_str.strip('/'):
title = ""
diff --git a/qutebrowser/browser/webkit/webview.py b/qutebrowser/browser/webkit/webview.py
index aaeba4033..16535e47f 100644
--- a/qutebrowser/browser/webkit/webview.py
+++ b/qutebrowser/browser/webkit/webview.py
@@ -28,7 +28,7 @@ from qutebrowser.qt.webkitwidgets import QWebView, QWebPage
from qutebrowser.config import config, stylesheet
from qutebrowser.keyinput import modeman
-from qutebrowser.utils import log, usertypes, utils, objreg, debug
+from qutebrowser.utils import log, usertypes, utils, objreg, debug, urlutils
from qutebrowser.browser.webkit import webpage
@@ -85,8 +85,7 @@ class WebView(QWebView):
stylesheet.set_register(self)
def __repr__(self):
- flags = QUrl.ComponentFormattingOption.EncodeUnicode
- urlstr = self.url().toDisplayString(flags) # type: ignore[arg-type]
+ urlstr = self.url().toDisplayString(urlutils.FormatOption.ENCODE_UNICODE)
url = utils.elide(urlstr, 100)
return utils.get_repr(self, tab_id=self._tab_id, url=url)
diff --git a/qutebrowser/keyinput/keyutils.py b/qutebrowser/keyinput/keyutils.py
index 0052cbb76..38eb563e9 100644
--- a/qutebrowser/keyinput/keyutils.py
+++ b/qutebrowser/keyinput/keyutils.py
@@ -352,7 +352,8 @@ def _unset_modifier_bits(
"""
if machinery.IS_QT5:
return cast(_ModifierType, modifiers & ~mask)
- return Qt.KeyboardModifier(modifiers.value & ~mask.value)
+ else:
+ return Qt.KeyboardModifier(modifiers.value & ~mask.value)
@dataclasses.dataclass(frozen=True, order=True)
diff --git a/qutebrowser/utils/jinja.py b/qutebrowser/utils/jinja.py
index 3e0fc7448..7b8dfc677 100644
--- a/qutebrowser/utils/jinja.py
+++ b/qutebrowser/utils/jinja.py
@@ -114,7 +114,7 @@ class Environment(jinja2.Environment):
url = QUrl('qute://resource')
url.setPath('/' + path)
urlutils.ensure_valid(url)
- urlstr = url.toString(QUrl.ComponentFormattingOption.FullyEncoded)
+ urlstr = url.toString(urlutils.FormatOption.ENCODED)
return urlstr
def _data_url(self, path: str) -> str:
diff --git a/qutebrowser/utils/urlutils.py b/qutebrowser/utils/urlutils.py
index d8a440f35..e9abb104b 100644
--- a/qutebrowser/utils/urlutils.py
+++ b/qutebrowser/utils/urlutils.py
@@ -26,7 +26,7 @@ import ipaddress
import posixpath
import urllib.parse
import mimetypes
-from typing import Optional, Tuple, Union, Iterable
+from typing import Optional, Tuple, Union, Iterable, cast
from qutebrowser.qt import machinery
from qutebrowser.qt.core import QUrl
@@ -44,6 +44,13 @@ from qutebrowser.browser.network import pac
if machinery.IS_QT6:
URL_FLAGS_T = Union[QUrl.UrlFormattingOption, QUrl.ComponentFormattingOption]
+ class FormatOption:
+ ENCODED = QUrl.ComponentFormattingOption.FullyEncoded
+ ENCODE_UNICODE = QUrl.ComponentFormattingOption.EncodeUnicode
+ DECODE_RESERVED = QUrl.ComponentFormattingOption.DecodeReserved
+
+ REMOVE_SCHEME = QUrl.UrlFormattingOption.RemoveScheme
+ REMOVE_PASSWORD = QUrl.UrlFormattingOption.RemovePassword
else:
URL_FLAGS_T = Union[
QUrl.FormattingOptions,
@@ -52,6 +59,34 @@ else:
QUrl.ComponentFormattingOptions,
]
+ class _QtFormattingOptions(QUrl.FormattingOptions):
+ """WORKAROUND for invalid stubs.
+
+ Teach mypy that | works for QUrl.FormattingOptions.
+ """
+ def __or__(self, f: URL_FLAGS_T) -> '_QtFormattingOptions':
+ return super() | f # type: ignore[operator,return-value]
+
+ class FormatOption:
+ """WORKAROUND for invalid stubs.
+
+ Pretend that all ComponentFormattingOption values are also valid
+ QUrl.FormattingOptions values, i.e. can be passed to QUrl.toString().
+ """
+ ENCODED = cast(
+ _QtFormattingOptions, QUrl.ComponentFormattingOption.FullyEncoded)
+ ENCODE_UNICODE = cast(
+ _QtFormattingOptions, QUrl.ComponentFormattingOption.EncodeUnicode)
+ DECODE_RESERVED = cast(
+ _QtFormattingOptions, QUrl.ComponentFormattingOption.DecodeReserved)
+
+ REMOVE_SCHEME = cast(
+ _QtFormattingOptions, QUrl.UrlFormattingOption.RemoveScheme)
+ REMOVE_PASSWORD = cast(
+ _QtFormattingOptions, QUrl.UrlFormattingOption.RemovePassword)
+
+
+
# URL schemes supported by QtWebEngine
WEBENGINE_SCHEMES = [
@@ -548,7 +583,7 @@ def file_url(path: str) -> str:
path: The absolute path to the local file
"""
url = QUrl.fromLocalFile(path)
- return url.toString(QUrl.ComponentFormattingOption.FullyEncoded)
+ return url.toString(FormatOption.ENCODED)
def data_url(mimetype: str, data: bytes) -> QUrl:
@@ -639,7 +674,7 @@ def parse_javascript_url(url: QUrl) -> str:
raise Error("URL contains unexpected components: {}"
.format(url.authority()))
- urlstr = url.toString(QUrl.ComponentFormattingOption.FullyEncoded)
+ urlstr = url.toString(FormatOption.ENCODED)
urlstr = urllib.parse.unquote(urlstr)
code = urlstr[len('javascript:'):]