Use builtin list/dict/set/... types for annotations

See https://peps.python.org/pep-0585/
and https://docs.python.org/3/whatsnew/3.9.html#type-hinting-generics-in-standard-collections

Done via:

    ruff check --select 'UP006' --fix --config 'target-version = "py39"' --unsafe-fixes

followed by removing unused imports:

    ruff check --select 'F401' --fix --config 'target-version = "py39"'

and a semi-manual review to find imports that are still needed (but ruff doesn't know about yet):

    git diff | grep '^-' | grep import | grep -v "from typing"

Also see #7098.
This commit is contained in:
Florian Bruhin 2024-10-13 15:06:01 +02:00
parent c32b8090ca
commit 97104b2000
92 changed files with 348 additions and 363 deletions

View File

@ -35,7 +35,7 @@ Possible values:
import inspect
from typing import Any, Callable, Protocol, Optional, Dict, cast
from typing import Any, Callable, Protocol, Optional, cast
from collections.abc import Iterable
from qutebrowser.utils import qtutils
@ -102,7 +102,7 @@ class _CmdHandlerType(Protocol):
Below, we cast the decorated function to _CmdHandlerType to make mypy aware of this.
"""
qute_args: Optional[Dict[str, 'command.ArgInfo']]
qute_args: Optional[dict[str, 'command.ArgInfo']]
def __call__(self, *args: Any, **kwargs: Any) -> Any:
...

View File

@ -29,7 +29,7 @@ import tempfile
import pathlib
import datetime
import argparse
from typing import Optional, List, Tuple
from typing import Optional
from collections.abc import Iterable
from qutebrowser.qt import machinery
@ -331,7 +331,7 @@ def _open_special_pages(args):
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window='last-focused')
pages: List[Tuple[str, bool, str]] = [
pages: list[tuple[str, bool, str]] = [
# state, condition, URL
('quickstart-done',
True,

View File

@ -9,7 +9,7 @@ import pathlib
import itertools
import functools
import dataclasses
from typing import (cast, TYPE_CHECKING, Any, Callable, List, Optional, Set, Type, Union, Tuple)
from typing import (cast, TYPE_CHECKING, Any, Callable, Optional, Union)
from collections.abc import Iterable, Sequence
from qutebrowser.qt import machinery
@ -60,7 +60,7 @@ def create(win_id: int,
mode_manager = modeman.instance(win_id)
if objects.backend == usertypes.Backend.QtWebEngine:
from qutebrowser.browser.webengine import webenginetab
tab_class: Type[AbstractTab] = webenginetab.WebEngineTab
tab_class: type[AbstractTab] = webenginetab.WebEngineTab
elif objects.backend == usertypes.Backend.QtWebKit:
from qutebrowser.browser.webkit import webkittab
tab_class = webkittab.WebKitTab
@ -142,7 +142,7 @@ class AbstractAction:
"""Attribute ``action`` of AbstractTab for Qt WebActions."""
action_base: Type[Union['QWebPage.WebAction', 'QWebEnginePage.WebAction']]
action_base: type[Union['QWebPage.WebAction', 'QWebEnginePage.WebAction']]
def __init__(self, tab: 'AbstractTab') -> None:
self._widget = cast(_WidgetType, None)
@ -639,7 +639,7 @@ class AbstractScroller(QObject):
def pos_px(self) -> QPoint:
raise NotImplementedError
def pos_perc(self) -> Tuple[int, int]:
def pos_perc(self) -> tuple[int, int]:
raise NotImplementedError
def to_perc(self, x: float = None, y: float = None) -> None:
@ -765,10 +765,10 @@ class AbstractHistory:
def _go_to_item(self, item: Any) -> None:
raise NotImplementedError
def back_items(self) -> List[Any]:
def back_items(self) -> list[Any]:
raise NotImplementedError
def forward_items(self) -> List[Any]:
def forward_items(self) -> list[Any]:
raise NotImplementedError
@ -1018,7 +1018,7 @@ class AbstractTab(QWidget):
# Note that we remember hosts here, without scheme/port:
# QtWebEngine/Chromium also only remembers hostnames, and certificates are
# for a given hostname anyways.
_insecure_hosts: Set[str] = set()
_insecure_hosts: set[str] = set()
# Sub-APIs initialized by subclasses
history: AbstractHistory

View File

@ -7,7 +7,7 @@
import os.path
import shlex
import functools
from typing import cast, Callable, Dict, Union, Optional
from typing import cast, Callable, Union, Optional
from qutebrowser.qt.widgets import QApplication, QTabBar
from qutebrowser.qt.core import Qt, QUrl, QEvent, QUrlQuery
@ -636,7 +636,7 @@ class CommandDispatcher:
widget = self._current_widget()
url = self._current_url()
handlers: Dict[str, Callable[..., QUrl]] = {
handlers: dict[str, Callable[..., QUrl]] = {
'prev': functools.partial(navigate.prevnext, prev=True),
'next': functools.partial(navigate.prevnext, prev=False),
'up': navigate.path_up,

View File

@ -13,7 +13,7 @@ import functools
import pathlib
import tempfile
import enum
from typing import Any, Dict, IO, List, Optional, Union
from typing import Any, IO, Optional, Union
from collections.abc import MutableSequence
from qutebrowser.qt.core import (pyqtSlot, pyqtSignal, Qt, QObject, QModelIndex,
@ -448,7 +448,7 @@ class AbstractDownloadItem(QObject):
UnsupportedAttribute, IO[bytes], None
] = UnsupportedAttribute()
self.raw_headers: Union[
UnsupportedAttribute, Dict[bytes, bytes]
UnsupportedAttribute, dict[bytes, bytes]
] = UnsupportedAttribute()
self._filename: Optional[str] = None
@ -900,7 +900,7 @@ class AbstractDownloadManager(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self.downloads: List[AbstractDownloadItem] = []
self.downloads: list[AbstractDownloadItem] = []
self._update_timer = usertypes.Timer(self, 'download-update')
self._update_timer.timeout.connect(self._update_gui)
self._update_timer.setInterval(_REFRESH_INTERVAL)

View File

@ -5,7 +5,7 @@
"""The ListView to display downloads in."""
import functools
from typing import Callable, Tuple, Union
from typing import Callable, Union
from collections.abc import MutableSequence
from qutebrowser.qt.core import pyqtSlot, QSize, Qt
@ -18,8 +18,8 @@ from qutebrowser.utils import qtutils, utils
_ActionListType = MutableSequence[
Union[
Tuple[None, None], # separator
Tuple[str, Callable[[], None]],
tuple[None, None], # separator
tuple[str, Callable[[], None]],
]
]

View File

@ -12,7 +12,7 @@ import functools
import glob
import textwrap
import dataclasses
from typing import cast, List, Tuple, Optional
from typing import cast, Optional
from collections.abc import Sequence
from qutebrowser.qt.core import pyqtSignal, QObject, QUrl
@ -208,9 +208,9 @@ class MatchingScripts:
"""All userscripts registered to run on a particular url."""
url: QUrl
start: List[GreasemonkeyScript] = dataclasses.field(default_factory=list)
end: List[GreasemonkeyScript] = dataclasses.field(default_factory=list)
idle: List[GreasemonkeyScript] = dataclasses.field(default_factory=list)
start: list[GreasemonkeyScript] = dataclasses.field(default_factory=list)
end: list[GreasemonkeyScript] = dataclasses.field(default_factory=list)
idle: list[GreasemonkeyScript] = dataclasses.field(default_factory=list)
@dataclasses.dataclass
@ -218,8 +218,8 @@ class LoadResults:
"""The results of loading all Greasemonkey scripts."""
successful: List[GreasemonkeyScript] = dataclasses.field(default_factory=list)
errors: List[Tuple[str, str]] = dataclasses.field(default_factory=list)
successful: list[GreasemonkeyScript] = dataclasses.field(default_factory=list)
errors: list[tuple[str, str]] = dataclasses.field(default_factory=list)
def successful_str(self) -> str:
"""Get a string with all successfully loaded scripts.
@ -295,10 +295,10 @@ class GreasemonkeyManager(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self._run_start: List[GreasemonkeyScript] = []
self._run_end: List[GreasemonkeyScript] = []
self._run_idle: List[GreasemonkeyScript] = []
self._in_progress_dls: List[downloads.AbstractDownloadItem] = []
self._run_start: list[GreasemonkeyScript] = []
self._run_end: list[GreasemonkeyScript] = []
self._run_idle: list[GreasemonkeyScript] = []
self._in_progress_dls: list[downloads.AbstractDownloadItem] = []
def load_scripts(self, *, force: bool = False) -> LoadResults:
"""Re-read Greasemonkey scripts from disk.

View File

@ -12,7 +12,7 @@ import html
import enum
import dataclasses
from string import ascii_lowercase
from typing import (TYPE_CHECKING, Callable, Dict, List, Optional, Set)
from typing import (TYPE_CHECKING, Callable, Optional)
from collections.abc import Iterable, Iterator, Mapping, MutableSequence, Sequence
from qutebrowser.qt.core import pyqtSignal, pyqtSlot, QObject, Qt, QUrl
@ -175,11 +175,11 @@ class HintContext:
add_history: bool
first: bool
baseurl: QUrl
args: List[str]
args: list[str]
group: str
all_labels: List[HintLabel] = dataclasses.field(default_factory=list)
labels: Dict[str, HintLabel] = dataclasses.field(default_factory=dict)
all_labels: list[HintLabel] = dataclasses.field(default_factory=list)
labels: dict[str, HintLabel] = dataclasses.field(default_factory=dict)
to_follow: Optional[str] = None
first_run: bool = True
filterstr: Optional[str] = None
@ -1033,7 +1033,7 @@ class WordHinter:
def __init__(self) -> None:
# will be initialized on first use.
self.words: Set[str] = set()
self.words: set[str] = set()
self.dictionary = None
def ensure_initialized(self) -> None:
@ -1143,7 +1143,7 @@ class WordHinter:
"""
self.ensure_initialized()
hints = []
used_hints: Set[str] = set()
used_hints: set[str] = set()
words = iter(self.words)
for elem in elems:
hint = self.new_hint_for(elem, used_hints, words)

View File

@ -6,7 +6,7 @@
import re
import posixpath
from typing import Optional, Set
from typing import Optional
from qutebrowser.qt.core import QUrl
@ -79,7 +79,7 @@ def incdec(url, count, inc_or_dec):
inc_or_dec: Either 'increment' or 'decrement'.
"""
urlutils.ensure_valid(url)
segments: Optional[Set[str]] = (
segments: Optional[set[str]] = (
set(config.val.url.incdec_segments)
)

View File

@ -4,7 +4,7 @@
"""Handling of proxies."""
from typing import Optional, List
from typing import Optional
from qutebrowser.qt.core import QUrl, pyqtSlot
from qutebrowser.qt.network import QNetworkProxy, QNetworkProxyFactory, QNetworkProxyQuery
@ -71,7 +71,7 @@ class ProxyFactory(QNetworkProxyFactory):
capabilities &= ~lookup_cap
proxy.setCapabilities(capabilities)
def queryProxy(self, query: QNetworkProxyQuery = QNetworkProxyQuery()) -> List[QNetworkProxy]:
def queryProxy(self, query: QNetworkProxyQuery = QNetworkProxyQuery()) -> list[QNetworkProxy]:
"""Get the QNetworkProxies for a query.
Args:

View File

@ -9,7 +9,7 @@ import os.path
import shutil
import functools
import dataclasses
from typing import Dict, IO, Optional
from typing import IO, Optional
from qutebrowser.qt.core import pyqtSlot, pyqtSignal, QTimer, QUrl
from qutebrowser.qt.widgets import QApplication
@ -73,7 +73,7 @@ class DownloadItem(downloads.AbstractDownloadItem):
"""
super().__init__(manager=manager, parent=manager)
self.fileobj: Optional[IO[bytes]] = None
self.raw_headers: Dict[bytes, bytes] = {}
self.raw_headers: dict[bytes, bytes] = {}
self._autoclose = True
self._retry_info = None

View File

@ -18,7 +18,7 @@ import textwrap
import urllib
import collections
import secrets
from typing import TypeVar, Callable, Dict, List, Optional, Union, Tuple
from typing import TypeVar, Callable, Optional, Union
from collections.abc import Sequence
from qutebrowser.qt.core import QUrlQuery, QUrl
@ -36,7 +36,7 @@ pyeval_output = ":pyeval was never called"
csrf_token: Optional[str] = None
_HANDLERS: Dict[str, "_HandlerCallable"] = {}
_HANDLERS: dict[str, "_HandlerCallable"] = {}
class Error(Exception):
@ -78,7 +78,7 @@ class Redirect(Exception):
# Return value: (mimetype, data) (encoded as utf-8 if a str is returned)
_HandlerRet = Tuple[str, Union[str, bytes]]
_HandlerRet = tuple[str, Union[str, bytes]]
_HandlerCallable = Callable[[QUrl], _HandlerRet]
_Handler = TypeVar('_Handler', bound=_HandlerCallable)
@ -106,7 +106,7 @@ class add_handler: # noqa: N801,N806 pylint: disable=invalid-name
return self._function(url)
def data_for_url(url: QUrl) -> Tuple[str, bytes]:
def data_for_url(url: QUrl) -> tuple[str, bytes]:
"""Get the data to show for the given URL.
Args:
@ -181,7 +181,7 @@ def qute_bookmarks(_url: QUrl) -> _HandlerRet:
@add_handler('tabs')
def qute_tabs(_url: QUrl) -> _HandlerRet:
"""Handler for qute://tabs. Display information about all open tabs."""
tabs: Dict[str, List[Tuple[str, str]]] = collections.defaultdict(list)
tabs: dict[str, list[tuple[str, str]]] = collections.defaultdict(list)
for win_id, window in objreg.window_registry.items():
if sip.isdeleted(window):
continue
@ -202,7 +202,7 @@ def qute_tabs(_url: QUrl) -> _HandlerRet:
def history_data(
start_time: float,
offset: int = None
) -> Sequence[Dict[str, Union[str, int]]]:
) -> Sequence[dict[str, Union[str, int]]]:
"""Return history data.
Arguments:

View File

@ -10,7 +10,7 @@ import html
import enum
import netrc
import tempfile
from typing import Callable, List, Optional
from typing import Callable, Optional
from collections.abc import Mapping, Iterable, Iterator
from qutebrowser.qt.core import QUrl, pyqtBoundSignal
@ -446,7 +446,7 @@ class FileSelectionMode(enum.Enum):
folder = enum.auto()
def choose_file(qb_mode: FileSelectionMode) -> List[str]:
def choose_file(qb_mode: FileSelectionMode) -> list[str]:
"""Select file(s)/folder for up-/downloading, using an external command.
Args:
@ -486,10 +486,10 @@ def choose_file(qb_mode: FileSelectionMode) -> List[str]:
def _execute_fileselect_command(
command: List[str],
command: list[str],
qb_mode: FileSelectionMode,
tmpfilename: Optional[str] = None
) -> List[str]:
) -> list[str]:
"""Execute external command to choose file.
Args:
@ -523,7 +523,7 @@ def _execute_fileselect_command(
def _validated_selected_files(
qb_mode: FileSelectionMode,
selected_files: List[str],
selected_files: list[str],
) -> Iterator[str]:
"""Validates selected files if they are.

View File

@ -4,7 +4,7 @@
"""Generic web element related code."""
from typing import Optional, Set, TYPE_CHECKING, Union, Dict
from typing import Optional, TYPE_CHECKING, Union
from collections.abc import Iterator
import collections.abc
@ -94,7 +94,7 @@ class AbstractWebElement(collections.abc.MutableMapping): # type: ignore[type-a
"""Get the geometry for this element."""
raise NotImplementedError
def classes(self) -> Set[str]:
def classes(self) -> set[str]:
"""Get a set of classes assigned to this element."""
raise NotImplementedError
@ -337,7 +337,7 @@ class AbstractWebElement(collections.abc.MutableMapping): # type: ignore[type-a
log.webelem.debug("Sending fake click to {!r} at position {} with "
"target {}".format(self, pos, click_target))
target_modifiers: Dict[usertypes.ClickTarget, KeyboardModifierType] = {
target_modifiers: dict[usertypes.ClickTarget, KeyboardModifierType] = {
usertypes.ClickTarget.normal: Qt.KeyboardModifier.NoModifier,
usertypes.ClickTarget.window: Qt.KeyboardModifier.AltModifier | Qt.KeyboardModifier.ShiftModifier,
usertypes.ClickTarget.tab: Qt.KeyboardModifier.ControlModifier,

View File

@ -125,7 +125,7 @@ import copy
import enum
import dataclasses
import collections
from typing import (Any, Optional, Set, Tuple, Union, List)
from typing import (Any, Optional, Union)
from collections.abc import Iterator, Mapping, MutableMapping, Sequence
from qutebrowser.config import config
@ -212,7 +212,7 @@ class _Setting:
return str(value)
return str(self.mapping[value])
def chromium_tuple(self, value: Any) -> Optional[Tuple[str, str]]:
def chromium_tuple(self, value: Any) -> Optional[tuple[str, str]]:
"""Get the Chromium key and value, or None if no value should be set."""
if self.mapping is not None and self.mapping[value] is None:
return None
@ -242,7 +242,7 @@ class _Definition:
def __init__(
self,
*args: _Setting,
mandatory: Set[str],
mandatory: set[str],
prefix: str,
switch_names: Mapping[Optional[str], str] = None,
) -> None:
@ -255,7 +255,7 @@ class _Definition:
else:
self._switch_names = {None: _BLINK_SETTINGS}
def prefixed_settings(self) -> Iterator[Tuple[str, _Setting]]:
def prefixed_settings(self) -> Iterator[tuple[str, _Setting]]:
"""Get all "prepared" settings.
Yields tuples which contain the Chromium setting key (e.g. 'blink-settings' or
@ -399,7 +399,7 @@ def settings(
*,
versions: version.WebEngineVersions,
special_flags: Sequence[str],
) -> Mapping[str, Sequence[Tuple[str, str]]]:
) -> Mapping[str, Sequence[tuple[str, str]]]:
"""Get necessary blink settings to configure dark mode for QtWebEngine.
Args:
@ -413,7 +413,7 @@ def settings(
variant = _variant(versions)
log.init.debug(f"Darkmode variant: {variant.name}")
result: Mapping[str, List[Tuple[str, str]]] = collections.defaultdict(list)
result: Mapping[str, list[tuple[str, str]]] = collections.defaultdict(list)
blink_settings_flag = f'--{_BLINK_SETTINGS}='
for flag in special_flags:

View File

@ -33,7 +33,7 @@ import dataclasses
import itertools
import functools
import subprocess
from typing import Any, List, Dict, Optional, Type, TYPE_CHECKING
from typing import Any, Optional, TYPE_CHECKING
from collections.abc import Iterator
from qutebrowser.qt import machinery
@ -196,7 +196,7 @@ class NotificationBridgePresenter(QObject):
def __init__(self, parent: QObject = None) -> None:
super().__init__(parent)
self._active_notifications: Dict[int, 'QWebEngineNotification'] = {}
self._active_notifications: dict[int, 'QWebEngineNotification'] = {}
self._adapter: Optional[AbstractNotificationAdapter] = None
config.instance.changed.connect(self._init_adapter)
@ -233,8 +233,8 @@ class NotificationBridgePresenter(QObject):
def _get_adapter_candidates(
self,
setting: str,
) -> List[Type[AbstractNotificationAdapter]]:
candidates: Dict[str, List[Type[AbstractNotificationAdapter]]] = {
) -> list[type[AbstractNotificationAdapter]]:
candidates: dict[str, list[type[AbstractNotificationAdapter]]] = {
"libnotify": [
DBusNotificationAdapter,
SystrayNotificationAdapter,
@ -666,7 +666,7 @@ class _ServerCapabilities:
kde_origin_name: bool
@classmethod
def from_list(cls, capabilities: List[str]) -> "_ServerCapabilities":
def from_list(cls, capabilities: list[str]) -> "_ServerCapabilities":
return cls(
actions='actions' in capabilities,
body_markup='body-markup' in capabilities,
@ -952,10 +952,10 @@ class DBusNotificationAdapter(AbstractNotificationAdapter):
qtutils.extract_enum_val(QMetaType.Type.QStringList),
)
def _get_hints_arg(self, *, origin_url: QUrl, icon: QImage) -> Dict[str, Any]:
def _get_hints_arg(self, *, origin_url: QUrl, icon: QImage) -> dict[str, Any]:
"""Get the hints argument for present()."""
origin_url_str = origin_url.toDisplayString()
hints: Dict[str, Any] = {
hints: dict[str, Any] = {
# Include the origin in case the user wants to do different things
# with different origin's notifications.
"x-qutebrowser-origin": origin_url_str,
@ -985,7 +985,7 @@ class DBusNotificationAdapter(AbstractNotificationAdapter):
title: str,
body: str,
actions: QDBusArgument,
hints: Dict[str, Any],
hints: dict[str, Any],
timeout: int,
) -> Any:
"""Wrapper around DBus call to use keyword args."""

View File

@ -5,7 +5,7 @@
"""QtWebEngine specific part of the web element API."""
from typing import (
TYPE_CHECKING, Any, Callable, Dict, Optional, Set, Tuple, Union)
TYPE_CHECKING, Any, Callable, Optional, Union)
from collections.abc import Iterator
from qutebrowser.qt.core import QRect, QEventLoop
@ -25,11 +25,11 @@ class WebEngineElement(webelem.AbstractWebElement):
_tab: "webenginetab.WebEngineTab"
def __init__(self, js_dict: Dict[str, Any],
def __init__(self, js_dict: dict[str, Any],
tab: 'webenginetab.WebEngineTab') -> None:
super().__init__(tab)
# Do some sanity checks on the data we get from JS
js_dict_types: Dict[str, Union[type, Tuple[type, ...]]] = {
js_dict_types: dict[str, Union[type, tuple[type, ...]]] = {
'id': int,
'text': str,
'value': (str, int, float),
@ -106,7 +106,7 @@ class WebEngineElement(webelem.AbstractWebElement):
log.stub()
return QRect()
def classes(self) -> Set[str]:
def classes(self) -> set[str]:
"""Get a list of classes assigned to this element."""
return set(self._js_dict['class_name'].split())

View File

@ -12,7 +12,7 @@ Module attributes:
import os
import operator
import pathlib
from typing import cast, Any, List, Optional, Tuple, Union, TYPE_CHECKING
from typing import cast, Any, Optional, Union, TYPE_CHECKING
from qutebrowser.qt import machinery
from qutebrowser.qt.gui import QFont
@ -509,7 +509,7 @@ def _init_default_settings():
- Make sure the devtools always get images/JS permissions.
- On Qt 6, make sure files in the data path can load external resources.
"""
devtools_settings: List[Tuple[str, Any]] = [
devtools_settings: list[tuple[str, Any]] = [
('content.javascript.enabled', True),
('content.images', True),
('content.cookies.accept', 'all'),
@ -522,7 +522,7 @@ def _init_default_settings():
hide_userconfig=True)
if machinery.IS_QT6:
userscripts_settings: List[Tuple[str, Any]] = [
userscripts_settings: list[tuple[str, Any]] = [
("content.local_content_can_access_remote_urls", True),
("content.local_content_can_access_file_urls", False),
]

View File

@ -5,7 +5,7 @@
"""The main browser widget for QtWebEngine."""
import mimetypes
from typing import List, Optional
from typing import Optional
from collections.abc import Iterable
from qutebrowser.qt import machinery
@ -317,7 +317,7 @@ class WebEnginePage(QWebEnginePage):
mode: QWebEnginePage.FileSelectionMode,
old_files: Iterable[Optional[str]],
accepted_mimetypes: Iterable[Optional[str]],
) -> List[str]:
) -> list[str]:
"""Override chooseFiles to (optionally) invoke custom file uploader."""
accepted_mimetypes_filtered = [m for m in accepted_mimetypes if m is not None]
old_files_filtered = [f for f in old_files if f is not None]

View File

@ -8,7 +8,6 @@ import email.headerregistry
import email.errors
import dataclasses
import os.path
from typing import Type
from qutebrowser.qt.network import QNetworkRequest
@ -25,7 +24,7 @@ class DefectWrapper:
"""Wrapper around a email.error for comparison."""
error_class: Type[email.errors.MessageDefect]
error_class: type[email.errors.MessageDefect]
line: str
def __eq__(self, other):

View File

@ -19,7 +19,7 @@ import email.mime.multipart
import email.message
import quopri
import dataclasses
from typing import Set, Tuple, Callable
from typing import Callable
from collections.abc import MutableMapping
from qutebrowser.qt.core import QUrl
@ -178,7 +178,7 @@ class MHTMLWriter:
return msg
_PendingDownloadType = Set[Tuple[QUrl, downloads.AbstractDownloadItem]]
_PendingDownloadType = set[tuple[QUrl, downloads.AbstractDownloadItem]]
class _Downloader:

View File

@ -7,7 +7,7 @@
import collections
import html
import dataclasses
from typing import TYPE_CHECKING, Dict, Optional, Set
from typing import TYPE_CHECKING, Optional
from collections.abc import MutableMapping
from qutebrowser.qt.core import pyqtSlot, pyqtSignal, QUrl, QByteArray
@ -30,7 +30,7 @@ if TYPE_CHECKING:
HOSTBLOCK_ERROR_STRING = '%HOSTBLOCK%'
_proxy_auth_cache: Dict['ProxyId', 'prompt.AuthInfo'] = {}
_proxy_auth_cache: dict['ProxyId', 'prompt.AuthInfo'] = {}
@dataclasses.dataclass(frozen=True)
@ -111,7 +111,7 @@ def init():
_SavedErrorsType = MutableMapping[
urlutils.HostTupleType,
Set[certificateerror.CertificateErrorWrapper],
set[certificateerror.CertificateErrorWrapper],
]

View File

@ -4,7 +4,7 @@
"""Utilities related to QWebHistory."""
from typing import Any, List
from typing import Any
from collections.abc import Mapping
from qutebrowser.qt.core import QByteArray, QDataStream, QIODevice, QUrl
@ -67,7 +67,7 @@ def serialize(items):
"""
data = QByteArray()
stream = QDataStream(data, QIODevice.OpenModeFlag.ReadWrite)
user_data: List[Mapping[str, Any]] = []
user_data: list[Mapping[str, Any]] = []
current_idx = None

View File

@ -4,7 +4,7 @@
"""QtWebKit specific part of the web element API."""
from typing import cast, TYPE_CHECKING, List, Optional, Set
from typing import cast, TYPE_CHECKING, Optional
from collections.abc import Iterator
from qutebrowser.qt.core import QRect, Qt
@ -91,7 +91,7 @@ class WebKitElement(webelem.AbstractWebElement):
self._check_vanished()
return self._elem.geometry()
def classes(self) -> Set[str]:
def classes(self) -> set[str]:
self._check_vanished()
return set(self._elem.classes())
@ -365,7 +365,7 @@ class WebKitElement(webelem.AbstractWebElement):
super()._click_fake_event(click_target)
def get_child_frames(startframe: QWebFrame) -> List[QWebFrame]:
def get_child_frames(startframe: QWebFrame) -> list[QWebFrame]:
"""Get all children recursively of a given QWebFrame.
Loosely based on https://blog.nextgenetics.net/?e=64
@ -379,7 +379,7 @@ def get_child_frames(startframe: QWebFrame) -> List[QWebFrame]:
results = []
frames = [startframe]
while frames:
new_frames: List[QWebFrame] = []
new_frames: list[QWebFrame] = []
for frame in frames:
results.append(frame)
new_frames += frame.childFrames()

View File

@ -7,7 +7,6 @@
Defined here to avoid circular dependency hell.
"""
from typing import List
import difflib
@ -21,7 +20,7 @@ class NoSuchCommandError(Error):
"""Raised when a command isn't found."""
@classmethod
def for_cmd(cls, cmd: str, all_commands: List[str] = None) -> "NoSuchCommandError":
def for_cmd(cls, cmd: str, all_commands: list[str] = None) -> "NoSuchCommandError":
"""Raise an exception for the given command."""
suffix = ''
if all_commands:

View File

@ -9,7 +9,7 @@ import collections
import traceback
import typing
import dataclasses
from typing import (Any, Tuple, Union, List, Optional,
from typing import (Any, Union, Optional,
Callable)
from collections.abc import MutableMapping, MutableSequence
@ -31,7 +31,7 @@ class ArgInfo:
metavar: Optional[str] = None
flag: Optional[str] = None
completion: Optional[Callable[..., completionmodel.CompletionModel]] = None
choices: Optional[List[str]] = None
choices: Optional[list[str]] = None
class Command:
@ -106,10 +106,10 @@ class Command:
self.parser.add_argument('-h', '--help', action=argparser.HelpAction,
default=argparser.SUPPRESS, nargs=0,
help=argparser.SUPPRESS)
self.opt_args: MutableMapping[str, Tuple[str, str]] = collections.OrderedDict()
self.opt_args: MutableMapping[str, tuple[str, str]] = collections.OrderedDict()
self.namespace = None
self._count = None
self.pos_args: MutableSequence[Tuple[str, str]] = []
self.pos_args: MutableSequence[tuple[str, str]] = []
self.flags_with_args: MutableSequence[str] = []
self._has_vararg = False

View File

@ -5,7 +5,6 @@
"""Module for parsing commands entered into the browser."""
import dataclasses
from typing import List
from collections.abc import Iterator
from qutebrowser.commands import cmdexc, command
@ -19,8 +18,8 @@ class ParseResult:
"""The result of parsing a commandline."""
cmd: command.Command
args: List[str]
cmdline: List[str]
args: list[str]
cmdline: list[str]
class CommandParser:
@ -108,7 +107,7 @@ class CommandParser:
for sub in sub_texts:
yield self.parse(sub, **kwargs)
def parse_all(self, text: str, **kwargs: bool) -> List[ParseResult]:
def parse_all(self, text: str, **kwargs: bool) -> list[ParseResult]:
"""Wrapper over _parse_all_gen."""
return list(self._parse_all_gen(text, **kwargs))
@ -162,7 +161,7 @@ class CommandParser:
cmdstr = matches[0]
return cmdstr
def _split_args(self, cmd: command.Command, argstr: str, keep: bool) -> List[str]:
def _split_args(self, cmd: command.Command, argstr: str, keep: bool) -> list[str]:
"""Split the arguments from an arg string.
Args:

View File

@ -7,7 +7,7 @@
import traceback
import re
import contextlib
from typing import TYPE_CHECKING, Callable, Dict, Tuple
from typing import TYPE_CHECKING, Callable
from collections.abc import Iterator, Mapping, MutableMapping
from qutebrowser.qt.core import pyqtSlot, QUrl, QObject
@ -22,7 +22,7 @@ if TYPE_CHECKING:
_ReplacementFunction = Callable[['tabbedbrowser.TabbedBrowser'], str]
last_command: Dict[usertypes.KeyMode, Tuple[str, int]] = {}
last_command: dict[usertypes.KeyMode, tuple[str, int]] = {}
def _url(tabbed_browser):
@ -39,7 +39,7 @@ def _url(tabbed_browser):
def _init_variable_replacements() -> Mapping[str, _ReplacementFunction]:
"""Return a dict from variable replacements to fns processing them."""
replacements: Dict[str, _ReplacementFunction] = {
replacements: dict[str, _ReplacementFunction] = {
'url': lambda tb: _url(tb).toString(
QUrl.ComponentFormattingOption.FullyEncoded | QUrl.UrlFormattingOption.RemovePassword),
'url:pretty': lambda tb: _url(tb).toString(

View File

@ -7,7 +7,7 @@
import os
import os.path
import tempfile
from typing import cast, Any, Tuple
from typing import cast, Any
from collections.abc import MutableMapping
from qutebrowser.qt.core import pyqtSignal, pyqtSlot, QObject, QSocketNotifier
@ -107,7 +107,7 @@ class _BaseUserscriptRunner(QObject):
self._env: MutableMapping[str, str] = {}
self._text_stored = False
self._html_stored = False
self._args: Tuple[Any, ...] = ()
self._args: tuple[Any, ...] = ()
self._kwargs = {}
def store_text(self, text):

View File

@ -14,7 +14,7 @@ is harder to achieve via pathlib.
import glob
import os
import os.path
from typing import List, Optional
from typing import Optional
from collections.abc import Iterable
from qutebrowser.qt.core import QAbstractListModel, QModelIndex, QObject, Qt, QUrl
@ -29,7 +29,7 @@ class FilePathCategory(QAbstractListModel, BaseCategory):
def __init__(self, name: str, parent: QObject = None) -> None:
super().__init__(parent)
self._paths: List[str] = []
self._paths: list[str] = []
self.name = name
self.columns_to_filter = [0]

View File

@ -5,7 +5,6 @@
"""Completion category that uses a list of tuples as a data source."""
import re
from typing import Tuple
from collections.abc import Iterable
from qutebrowser.qt.core import QSortFilterProxyModel, QRegularExpression
@ -22,7 +21,7 @@ class ListCategory(QSortFilterProxyModel, BaseCategory):
def __init__(self,
name: str,
items: Iterable[Tuple[str, ...]],
items: Iterable[tuple[str, ...]],
sort: bool = True,
delete_func: util.DeleteFuncType = None,
parent: QWidget = None):

View File

@ -6,7 +6,6 @@
import datetime
import itertools
from typing import List, Tuple
from collections.abc import Sequence
from qutebrowser.config import config, configdata
@ -114,7 +113,7 @@ def _tabs(*, win_id_filter=lambda _win_id: True, add_win_id=True, cur_win_id=Non
tabs_are_windows = config.val.tabs.tabs_are_windows
# list storing all single-tabbed windows when tabs_are_windows
windows: List[Tuple[str, str, str, str]] = []
windows: list[tuple[str, str, str, str]] = []
for win_id in objreg.window_registry:
if not win_id_filter(win_id):
@ -124,7 +123,7 @@ def _tabs(*, win_id_filter=lambda _win_id: True, add_win_id=True, cur_win_id=Non
window=win_id)
if tabbed_browser.is_shutting_down:
continue
tab_entries: List[Tuple[str, str, str, str]] = []
tab_entries: list[tuple[str, str, str, str]] = []
for idx in range(tabbed_browser.widget.count()):
tab = tabbed_browser.widget.widget(idx)
tab_str = ("{}/{}".format(win_id, idx + 1) if add_win_id

View File

@ -4,7 +4,6 @@
"""Function to return the url completion model for the `open` command."""
from typing import Dict
from collections.abc import Sequence
from qutebrowser.completion.models import (completionmodel, filepathcategory,
@ -59,7 +58,7 @@ def url(*, info):
in sorted(config.val.url.searchengines.items())
if k != 'DEFAULT']
categories = config.val.completion.open_categories
models: Dict[str, BaseCategory] = {}
models: dict[str, BaseCategory] = {}
if searchengines and 'searchengines' in categories:
models['searchengines'] = listcategory.ListCategory(

View File

@ -9,7 +9,7 @@ import posixpath
import zipfile
import logging
import pathlib
from typing import cast, IO, Set
from typing import cast, IO
from qutebrowser.qt.core import QUrl
@ -92,8 +92,8 @@ class HostBlocker:
) -> None:
self.enabled = _should_be_used()
self._has_basedir = has_basedir
self._blocked_hosts: Set[str] = set()
self._config_blocked_hosts: Set[str] = set()
self._blocked_hosts: set[str] = set()
self._config_blocked_hosts: set[str] = set()
self._local_hosts_file = str(data_dir / "blocked-hosts")
self.update_files()
@ -139,7 +139,7 @@ class HostBlocker:
)
info.block()
def _read_hosts_line(self, raw_line: bytes) -> Set[str]:
def _read_hosts_line(self, raw_line: bytes) -> set[str]:
"""Read hosts from the given line.
Args:
@ -175,7 +175,7 @@ class HostBlocker:
return filtered_hosts
def _read_hosts_file(self, filename: str, target: Set[str]) -> bool:
def _read_hosts_file(self, filename: str, target: set[str]) -> bool:
"""Read hosts from the given filename.
Args:

View File

@ -4,7 +4,7 @@
"""Scrolling-related commands."""
from typing import Dict, Callable
from typing import Callable
from qutebrowser.api import cmdutils, apitypes
@ -41,7 +41,7 @@ def scroll(tab: apitypes.Tab, direction: str, count: int = 1) -> None:
count: multiplier
"""
# FIXME:mypy Use a callback protocol to enforce having 'count'?
funcs: Dict[str, Callable[..., None]] = {
funcs: dict[str, Callable[..., None]] = {
'up': tab.scroller.up,
'down': tab.scroller.down,
'left': tab.scroller.left,

View File

@ -6,7 +6,7 @@
import os
import functools
from typing import IO, List, Optional
from typing import IO, Optional
from qutebrowser.qt.core import QUrl, QObject, pyqtSignal
@ -47,11 +47,11 @@ class BlocklistDownloads(QObject):
single_download_finished = pyqtSignal(object) # arg: the file object
all_downloads_finished = pyqtSignal(int) # arg: download count
def __init__(self, urls: List[QUrl], parent: Optional[QObject] = None) -> None:
def __init__(self, urls: list[QUrl], parent: Optional[QObject] = None) -> None:
super().__init__(parent)
self._urls = urls
self._in_progress: List[downloads.TempDownload] = []
self._in_progress: list[downloads.TempDownload] = []
self._done_count = 0
self._finished_registering_downloads = False
self._started = False

View File

@ -7,7 +7,7 @@
import copy
import contextlib
import functools
from typing import (TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, cast)
from typing import (TYPE_CHECKING, Any, Callable, Optional, cast)
from collections.abc import Iterator, Mapping, MutableMapping, MutableSequence
from qutebrowser.qt.core import pyqtSignal, QObject, QUrl
@ -29,7 +29,7 @@ key_instance = cast('KeyConfig', None)
cache = cast('configcache.ConfigCache', None)
# Keeping track of all change filters to validate them later.
change_filters: List["change_filter"] = []
change_filters: list["change_filter"] = []
# Sentinel
UNSET = object()
@ -131,7 +131,7 @@ class KeyConfig:
_config: The Config object to be used.
"""
_ReverseBindings = Dict[str, MutableSequence[str]]
_ReverseBindings = dict[str, MutableSequence[str]]
def __init__(self, config: 'Config') -> None:
self._config = config
@ -143,7 +143,7 @@ class KeyConfig:
if mode not in configdata.DATA['bindings.default'].default:
raise configexc.KeybindingError("Invalid mode {}!".format(mode))
def get_bindings_for(self, mode: str) -> Dict[keyutils.KeySequence, str]:
def get_bindings_for(self, mode: str) -> dict[keyutils.KeySequence, str]:
"""Get the combined bindings for the given mode."""
bindings = dict(val.bindings.default[mode])
for key, binding in val.bindings.commands[mode].items():
@ -291,7 +291,7 @@ class Config(QObject):
yaml_config: 'configfiles.YamlConfig',
parent: QObject = None) -> None:
super().__init__(parent)
self._mutables: MutableMapping[str, Tuple[Any, Any]] = {}
self._mutables: MutableMapping[str, tuple[Any, Any]] = {}
self._yaml = yaml_config
self._init_values()
self.yaml_loaded = False
@ -554,7 +554,7 @@ class Config(QObject):
Return:
The changed config part as string.
"""
lines: List[str] = []
lines: list[str] = []
for values in sorted(self, key=lambda v: v.opt.name):
lines += values.dump(include_hidden=include_hidden)

View File

@ -4,7 +4,7 @@
"""Implementation of a basic config cache."""
from typing import Any, Dict
from typing import Any
from qutebrowser.config import config
@ -22,7 +22,7 @@ class ConfigCache:
"""
def __init__(self) -> None:
self._cache: Dict[str, Any] = {}
self._cache: dict[str, Any] = {}
config.instance.changed.connect(self._on_config_changed)
def _on_config_changed(self, attr: str) -> None:

View File

@ -6,7 +6,7 @@
import os.path
import contextlib
from typing import TYPE_CHECKING, List, Optional, Any, Tuple
from typing import TYPE_CHECKING, Optional, Any
from collections.abc import Iterator
from qutebrowser.qt.core import QUrl, QUrlQuery
@ -474,7 +474,7 @@ class ConfigCommands:
raise cmdutils.CommandError("{} already exists - use --force to "
"overwrite!".format(filename))
options: List[Tuple[Optional[urlmatch.UrlPattern], configdata.Option, Any]] = []
options: list[tuple[Optional[urlmatch.UrlPattern], configdata.Option, Any]] = []
if defaults:
options = [(None, opt, opt.default)
for _name, opt in sorted(configdata.DATA.items())]

View File

@ -9,7 +9,7 @@ Module attributes:
DATA: A dict of Option objects after init() has been called.
"""
from typing import (Any, Dict, List, Optional, Tuple, Union, NoReturn, cast)
from typing import (Any, Optional, Union, NoReturn, cast)
from collections.abc import Iterable, Mapping, MutableMapping, Sequence
import functools
import dataclasses
@ -53,8 +53,8 @@ class Migrations:
deleted: A list of option names which have been removed.
"""
renamed: Dict[str, str] = dataclasses.field(default_factory=dict)
deleted: List[str] = dataclasses.field(default_factory=list)
renamed: dict[str, str] = dataclasses.field(default_factory=dict)
deleted: list[str] = dataclasses.field(default_factory=list)
def _raise_invalid_node(name: str, what: str, node: Any) -> NoReturn:
@ -186,7 +186,7 @@ def _parse_yaml_backends(
def _read_yaml(
yaml_data: str,
) -> Tuple[Mapping[str, Option], Migrations]:
) -> tuple[Mapping[str, Option], Migrations]:
"""Read config data from a YAML file.
Args:

View File

@ -6,7 +6,7 @@
import difflib
import dataclasses
from typing import Any, Optional, Union, List
from typing import Any, Optional, Union
from collections.abc import Mapping, Sequence
from qutebrowser.utils import usertypes, log
@ -78,7 +78,7 @@ class NoOptionError(Error):
"""Raised when an option was not found."""
def __init__(self, option: str, *,
all_names: List[str] = None,
all_names: list[str] = None,
deleted: bool = False,
renamed: str = None) -> None:
if deleted:

View File

@ -14,7 +14,7 @@ import traceback
import configparser
import contextlib
import re
from typing import (TYPE_CHECKING, Any, Dict, List, Optional, Tuple, cast)
from typing import (TYPE_CHECKING, Any, Optional, cast)
from collections.abc import Iterable, Iterator, Mapping, MutableMapping
import yaml
@ -34,7 +34,7 @@ if TYPE_CHECKING:
state = cast('StateConfig', None)
_SettingsType = Dict[str, Dict[str, Any]]
_SettingsType = dict[str, dict[str, Any]]
class VersionChange(enum.Enum):
@ -55,7 +55,7 @@ class VersionChange(enum.Enum):
This is intended to use filters like "major" (show major only), "minor" (show
major/minor) or "patch" (show all changes).
"""
allowed_values: Dict[str, List[VersionChange]] = {
allowed_values: dict[str, list[VersionChange]] = {
'major': [VersionChange.major],
'minor': [VersionChange.major, VersionChange.minor],
'patch': [VersionChange.major, VersionChange.minor, VersionChange.patch],
@ -250,7 +250,7 @@ class YamlConfig(QObject):
'autoconfig.yml')
self._dirty = False
self._values: Dict[str, configutils.Values] = {}
self._values: dict[str, configutils.Values] = {}
for name, opt in configdata.DATA.items():
self._values[name] = configutils.Values(opt)
@ -702,7 +702,7 @@ class ConfigAPI:
):
self._config = conf
self._keyconfig = keyconfig
self.errors: List[configexc.ConfigErrorDesc] = []
self.errors: list[configexc.ConfigErrorDesc] = []
self.configdir = pathlib.Path(standarddir.config())
self.datadir = pathlib.Path(standarddir.data())
self._warn_autoconfig = warn_autoconfig
@ -803,8 +803,8 @@ class ConfigPyWriter:
def __init__(
self,
options: List[
Tuple[
options: list[
tuple[
Optional[urlmatch.UrlPattern],
configdata.Option,
Any

View File

@ -36,8 +36,7 @@ import functools
import operator
import json
import dataclasses
from typing import (Any, Callable, Dict as DictType,
List as ListType, Optional, Tuple, Union)
from typing import (Any, Callable, Optional, Union)
from re import Pattern
from collections.abc import Iterable, Iterator, Sequence
@ -67,7 +66,7 @@ BOOLEAN_STATES = {'1': True, 'yes': True, 'true': True, 'on': True,
'0': False, 'no': False, 'false': False, 'off': False}
_Completions = Optional[Iterable[Tuple[str, str]]]
_Completions = Optional[Iterable[tuple[str, str]]]
_StrUnset = Union[str, usertypes.Unset]
_UnsetNone = Union[None, usertypes.Unset]
_StrUnsetNone = Union[str, _UnsetNone]
@ -104,16 +103,16 @@ class ValidValues:
self,
*values: Union[
str,
DictType[str, Optional[str]],
Tuple[str, Optional[str]],
dict[str, Optional[str]],
tuple[str, Optional[str]],
],
generate_docs: bool = True,
others_permitted: bool = False
) -> None:
if not values:
raise ValueError("ValidValues with no values makes no sense!")
self.descriptions: DictType[str, str] = {}
self.values: ListType[str] = []
self.descriptions: dict[str, str] = {}
self.values: list[str] = []
self.generate_docs = generate_docs
self.others_permitted = others_permitted
for value in values:
@ -180,7 +179,7 @@ class BaseType:
def _basic_py_validation(
self, value: Any,
pytype: Union[type, Tuple[type, ...]]) -> None:
pytype: Union[type, tuple[type, ...]]) -> None:
"""Do some basic validation for Python values (emptyness, type).
Arguments:
@ -346,7 +345,7 @@ class MappingType(BaseType):
MAPPING: A mapping from config values to (translated_value, docs) tuples.
"""
MAPPING: DictType[str, Tuple[Any, Optional[str]]] = {}
MAPPING: dict[str, tuple[Any, Optional[str]]] = {}
def __init__(
self, *,
@ -498,7 +497,7 @@ class List(BaseType):
def get_valid_values(self) -> Optional[ValidValues]:
return self.valtype.get_valid_values()
def from_str(self, value: str) -> Optional[ListType]:
def from_str(self, value: str) -> Optional[list]:
self._basic_str_validation(value)
if not value:
return None
@ -513,15 +512,15 @@ class List(BaseType):
self.to_py(yaml_val)
return yaml_val
def from_obj(self, value: Optional[ListType]) -> ListType:
def from_obj(self, value: Optional[list]) -> list:
if value is None:
return []
return [self.valtype.from_obj(v) for v in value]
def to_py(
self,
value: Union[ListType, usertypes.Unset]
) -> Union[ListType, usertypes.Unset]:
value: Union[list, usertypes.Unset]
) -> Union[list, usertypes.Unset]:
self._basic_py_validation(value, list)
if isinstance(value, usertypes.Unset):
return value
@ -536,13 +535,13 @@ class List(BaseType):
"be set!".format(self.length))
return [self.valtype.to_py(v) for v in value]
def to_str(self, value: ListType) -> str:
def to_str(self, value: list) -> str:
if not value:
# An empty list is treated just like None -> empty string
return ''
return json.dumps(value)
def to_doc(self, value: ListType, indent: int = 0) -> str:
def to_doc(self, value: list, indent: int = 0) -> str:
if not value:
return 'empty'
@ -587,7 +586,7 @@ class ListOrValue(BaseType):
self.listtype = List(valtype=valtype, none_ok=none_ok, **kwargs)
self.valtype = valtype
def _val_and_type(self, value: Any) -> Tuple[Any, BaseType]:
def _val_and_type(self, value: Any) -> tuple[Any, BaseType]:
"""Get the value and type to use for to_str/to_doc/from_str."""
if isinstance(value, list):
if len(value) == 1:
@ -668,15 +667,15 @@ class FlagList(List):
)
self.valtype.valid_values = valid_values
def _check_duplicates(self, values: ListType) -> None:
def _check_duplicates(self, values: list) -> None:
if len(set(values)) != len(values):
raise configexc.ValidationError(
values, "List contains duplicate values!")
def to_py(
self,
value: Union[usertypes.Unset, ListType],
) -> Union[usertypes.Unset, ListType]:
value: Union[usertypes.Unset, list],
) -> Union[usertypes.Unset, list]:
vals = super().to_py(value)
if not isinstance(vals, usertypes.Unset):
self._check_duplicates(vals)
@ -1112,7 +1111,7 @@ class QtColor(BaseType):
kind = value[:openparen]
vals = value[openparen+1:-1].split(',')
converters: DictType[str, Callable[..., QColor]] = {
converters: dict[str, Callable[..., QColor]] = {
'rgba': QColor.fromRgb,
'rgb': QColor.fromRgb,
'hsva': QColor.fromHsv,
@ -1202,7 +1201,7 @@ class FontBase(BaseType):
(?P<family>.+) # mandatory font family""", re.VERBOSE)
@classmethod
def set_defaults(cls, default_family: ListType[str], default_size: str) -> None:
def set_defaults(cls, default_family: list[str], default_size: str) -> None:
"""Make sure default_family/default_size are available.
If the given family value (fonts.default_family in the config) is
@ -1375,7 +1374,7 @@ class Dict(BaseType):
self.fixed_keys = fixed_keys
self.required_keys = required_keys
def _validate_keys(self, value: DictType) -> None:
def _validate_keys(self, value: dict) -> None:
if (self.fixed_keys is not None and not
set(value.keys()).issubset(self.fixed_keys)):
raise configexc.ValidationError(
@ -1386,7 +1385,7 @@ class Dict(BaseType):
raise configexc.ValidationError(
value, "Required keys {}".format(self.required_keys))
def from_str(self, value: str) -> Optional[DictType]:
def from_str(self, value: str) -> Optional[dict]:
self._basic_str_validation(value)
if not value:
return None
@ -1401,14 +1400,14 @@ class Dict(BaseType):
self.to_py(yaml_val)
return yaml_val
def from_obj(self, value: Optional[DictType]) -> DictType:
def from_obj(self, value: Optional[dict]) -> dict:
if value is None:
return {}
return {self.keytype.from_obj(key): self.valtype.from_obj(val)
for key, val in value.items()}
def _fill_fixed_keys(self, value: DictType) -> DictType:
def _fill_fixed_keys(self, value: dict) -> dict:
"""Fill missing fixed keys with a None-value."""
if self.fixed_keys is None:
return value
@ -1419,8 +1418,8 @@ class Dict(BaseType):
def to_py(
self,
value: Union[DictType, _UnsetNone]
) -> Union[DictType, usertypes.Unset]:
value: Union[dict, _UnsetNone]
) -> Union[dict, usertypes.Unset]:
self._basic_py_validation(value, dict)
if isinstance(value, usertypes.Unset):
return value
@ -1436,13 +1435,13 @@ class Dict(BaseType):
for key, val in value.items()}
return self._fill_fixed_keys(d)
def to_str(self, value: DictType) -> str:
def to_str(self, value: dict) -> str:
if not value:
# An empty Dict is treated just like None -> empty string
return ''
return json.dumps(value, sort_keys=True)
def to_doc(self, value: DictType, indent: int = 0) -> str:
def to_doc(self, value: dict, indent: int = 0) -> str:
if not value:
return 'empty'
lines = ['\n']
@ -1596,8 +1595,8 @@ class ShellCommand(List):
def to_py(
self,
value: Union[ListType, usertypes.Unset],
) -> Union[ListType, usertypes.Unset]:
value: Union[list, usertypes.Unset],
) -> Union[list, usertypes.Unset]:
py_value = super().to_py(value)
if isinstance(py_value, usertypes.Unset):
return py_value
@ -1754,7 +1753,7 @@ class Padding(Dict):
def to_py( # type: ignore[override]
self,
value: Union[DictType, _UnsetNone],
value: Union[dict, _UnsetNone],
) -> Union[usertypes.Unset, PaddingValues]:
d = super().to_py(value)
if isinstance(d, usertypes.Unset):
@ -1907,8 +1906,8 @@ class ConfirmQuit(FlagList):
def to_py(
self,
value: Union[usertypes.Unset, ListType],
) -> Union[ListType, usertypes.Unset]:
value: Union[usertypes.Unset, list],
) -> Union[list, usertypes.Unset]:
values = super().to_py(value)
if isinstance(values, usertypes.Unset):
return values

View File

@ -9,7 +9,7 @@ import collections
import itertools
import operator
from typing import (
TYPE_CHECKING, Any, Dict, List, Optional, Set, Union)
TYPE_CHECKING, Any, Optional, Union)
from collections.abc import Iterator, Sequence, MutableMapping
from qutebrowser.qt.core import QUrl
@ -78,8 +78,8 @@ class Values:
self._vmap: MutableMapping[
Values._VmapKeyType, ScopedValue] = collections.OrderedDict()
# A map from domain parts to rules that fall under them.
self._domain_map: Dict[
Optional[str], Set[ScopedValue]] = collections.defaultdict(set)
self._domain_map: dict[
Optional[str], set[ScopedValue]] = collections.defaultdict(set)
for scoped in values:
self._add_scoped(scoped)
@ -203,7 +203,7 @@ class Values:
return self._get_fallback(fallback)
qtutils.ensure_valid(url)
candidates: List[ScopedValue] = []
candidates: list[ScopedValue] = []
# Urls trailing with '.' are equivalent to non-trailing types.
# urlutils strips them, so in order to match we will need to as well.
widened_hosts = urlutils.widened_hostnames(url.host().rstrip('.'))

View File

@ -8,7 +8,7 @@ import os
import sys
import argparse
import pathlib
from typing import Any, Dict, List, Optional, Tuple, Union, Callable
from typing import Any, Optional, Union, Callable
from collections.abc import Iterator, Sequence
from qutebrowser.qt import machinery
@ -24,7 +24,7 @@ _DISABLE_FEATURES = '--disable-features='
_BLINK_SETTINGS = '--blink-settings='
def qt_args(namespace: argparse.Namespace) -> List[str]:
def qt_args(namespace: argparse.Namespace) -> list[str]:
"""Get the Qt QApplication arguments based on an argparse namespace.
Args:
@ -78,7 +78,7 @@ def qt_args(namespace: argparse.Namespace) -> List[str]:
def _qtwebengine_features(
versions: version.WebEngineVersions,
special_flags: Sequence[str],
) -> Tuple[Sequence[str], Sequence[str]]:
) -> tuple[Sequence[str], Sequence[str]]:
"""Get a tuple of --enable-features/--disable-features flags for QtWebEngine.
Args:
@ -286,7 +286,7 @@ _SettingValueType = Union[
Optional[str],
],
]
_WEBENGINE_SETTINGS: Dict[str, Dict[Any, Optional[_SettingValueType]]] = {
_WEBENGINE_SETTINGS: dict[str, dict[Any, Optional[_SettingValueType]]] = {
'qt.force_software_rendering': {
'software-opengl': None,
'qt-quick': None,

View File

@ -5,7 +5,7 @@
"""Handling of Qt qss stylesheets."""
import functools
from typing import Optional, FrozenSet
from typing import Optional
from qutebrowser.qt.core import pyqtSlot, QObject
from qutebrowser.qt.widgets import QWidget
@ -72,7 +72,7 @@ class _StyleSheetObserver(QObject):
self._stylesheet = stylesheet
if update:
self._options: Optional[FrozenSet[str]] = jinja.template_config_variables(
self._options: Optional[frozenset[str]] = jinja.template_config_variables(
self._stylesheet)
else:
self._options = None

View File

@ -8,7 +8,7 @@ import re
import argparse
import functools
import dataclasses
from typing import Any, Callable, Dict, Optional, Union
from typing import Any, Callable, Optional, Union
from qutebrowser.qt.core import QUrl, pyqtSlot, qVersion
from qutebrowser.qt.gui import QFont
@ -86,10 +86,10 @@ class AbstractSettings:
"""Abstract base class for settings set via QWeb(Engine)Settings."""
_ATTRIBUTES: Dict[str, AttributeInfo] = {}
_FONT_SIZES: Dict[str, Any] = {}
_FONT_FAMILIES: Dict[str, Any] = {}
_FONT_TO_QFONT: Dict[Any, QFont.StyleHint] = {}
_ATTRIBUTES: dict[str, AttributeInfo] = {}
_FONT_SIZES: dict[str, Any] = {}
_FONT_FAMILIES: dict[str, Any] = {}
_FONT_TO_QFONT: dict[Any, QFont.StyleHint] = {}
def __init__(self, settings: Any) -> None:
self._settings = settings

View File

@ -6,7 +6,7 @@
import enum
import dataclasses
from typing import Callable, List, Optional
from typing import Callable, Optional
from qutebrowser.qt.core import QUrl
@ -89,7 +89,7 @@ class Request:
InterceptorType = Callable[[Request], None]
_interceptors: List[InterceptorType] = []
_interceptors: list[InterceptorType] = []
def register(interceptor: InterceptorType) -> None:

View File

@ -10,7 +10,7 @@ import pathlib
import importlib
import argparse
import dataclasses
from typing import Callable, List, Optional, Tuple
from typing import Callable, Optional
from collections.abc import Iterator
from qutebrowser.qt.core import pyqtSlot
@ -22,7 +22,7 @@ from qutebrowser.misc import objects
# ModuleInfo objects for all loaded plugins
_module_infos: List["ModuleInfo"] = []
_module_infos: list["ModuleInfo"] = []
InitHookType = Callable[['InitContext'], None]
ConfigChangedHookType = Callable[[], None]
@ -48,8 +48,8 @@ class ModuleInfo:
skip_hooks: bool = False
init_hook: Optional[InitHookType] = None
config_changed_hooks: List[
Tuple[
config_changed_hooks: list[
tuple[
Optional[str],
ConfigChangedHookType,
]

View File

@ -18,7 +18,7 @@ handle what we actually think we do.
import itertools
import dataclasses
from typing import List, Optional, Union, overload, cast
from typing import Optional, Union, overload, cast
from collections.abc import Iterator, Iterable, Mapping
from qutebrowser.qt import machinery
@ -524,7 +524,7 @@ class KeySequence:
_MAX_LEN = 4
def __init__(self, *keys: KeyInfo) -> None:
self._sequences: List[QKeySequence] = []
self._sequences: list[QKeySequence] = []
for sub in utils.chunk(keys, self._MAX_LEN):
try:
args = [info.to_qt() for info in sub]
@ -547,7 +547,7 @@ class KeySequence:
"""Iterate over KeyInfo objects."""
# FIXME:mypy Stubs seem to be unaware that iterating a QKeySequence produces
# _KeyInfoType
sequences = cast(List[Iterable[_KeyInfoType]], self._sequences)
sequences = cast(list[Iterable[_KeyInfoType]], self._sequences)
for combination in itertools.chain.from_iterable(sequences):
yield KeyInfo.from_qt(combination)
@ -720,7 +720,7 @@ class KeySequence:
mappings: Mapping['KeySequence', 'KeySequence']
) -> 'KeySequence':
"""Get a new KeySequence with the given mappings applied."""
infos: List[KeyInfo] = []
infos: list[KeyInfo] = []
for info in self:
key_seq = KeySequence(info)
if key_seq in mappings:

View File

@ -5,7 +5,7 @@
"""Keyboard macro system."""
from typing import cast, Dict, List, Optional, Tuple
from typing import cast, Optional
from qutebrowser.commands import runners
from qutebrowser.api import cmdutils
@ -13,7 +13,7 @@ from qutebrowser.keyinput import modeman
from qutebrowser.utils import message, objreg, usertypes
_CommandType = Tuple[str, int] # command, type
_CommandType = tuple[str, int] # command, type
macro_recorder = cast('MacroRecorder', None)
@ -32,9 +32,9 @@ class MacroRecorder:
"""
def __init__(self) -> None:
self._macros: Dict[str, List[_CommandType]] = {}
self._macros: dict[str, list[_CommandType]] = {}
self._recording_macro: Optional[str] = None
self._macro_count: Dict[int, int] = {}
self._macro_count: dict[int, int] = {}
self._last_register: Optional[str] = None
@cmdutils.register(instance='macro-recorder')

View File

@ -6,7 +6,7 @@
import functools
import dataclasses
from typing import Callable, Union, Set, cast
from typing import Callable, Union, cast
from collections.abc import Mapping, MutableMapping
from qutebrowser.qt import machinery
@ -253,7 +253,7 @@ class ModeManager(QObject):
self.parsers: ParserDictType = {}
self._prev_mode = usertypes.KeyMode.normal
self.mode = usertypes.KeyMode.normal
self._releaseevents_to_pass: Set[KeyEvent] = set()
self._releaseevents_to_pass: set[KeyEvent] = set()
# Set after __init__
self.hintmanager = cast(hints.HintManager, None)

View File

@ -8,7 +8,7 @@ import binascii
import base64
import itertools
import functools
from typing import List, Optional, Tuple, cast
from typing import Optional, cast
from collections.abc import MutableSequence
from qutebrowser.qt import machinery
@ -101,7 +101,7 @@ def get_target_window():
return None
_OverlayInfoType = Tuple[QWidget, pyqtBoundSignal, bool, str]
_OverlayInfoType = tuple[QWidget, pyqtBoundSignal, bool, str]
class MainWindow(QWidget):
@ -415,7 +415,7 @@ class MainWindow(QWidget):
self._vbox.removeWidget(self.tabbed_browser.widget)
self._vbox.removeWidget(self._downloadview)
self._vbox.removeWidget(self.status)
widgets: List[QWidget] = [self.tabbed_browser.widget]
widgets: list[QWidget] = [self.tabbed_browser.widget]
downloads_position = config.val.downloads.position
if downloads_position == 'top':

View File

@ -9,7 +9,7 @@ import html
import collections
import functools
import dataclasses
from typing import Deque, Optional, cast
from typing import Optional, cast
from collections.abc import MutableSequence
from qutebrowser.qt.core import (pyqtSlot, pyqtSignal, Qt, QTimer, QDir, QModelIndex,
@ -90,7 +90,7 @@ class PromptQueue(QObject):
self._question = None
self._shutting_down = False
self._loops: MutableSequence[qtutils.EventLoop] = []
self._queue: Deque[usertypes.Question] = collections.deque()
self._queue: collections.deque[usertypes.Question] = collections.deque()
message.global_bridge.mode_left.connect(self._on_mode_left)
def __repr__(self):

View File

@ -10,7 +10,7 @@ import weakref
import datetime
import dataclasses
from typing import (
Any, Deque, List, Optional, Tuple)
Any, Optional)
from collections.abc import Mapping, MutableMapping, MutableSequence
from qutebrowser.qt.widgets import QSizePolicy, QWidget, QApplication
@ -59,10 +59,10 @@ class TabDeque:
size = config.val.tabs.focus_stack_size
if size < 0:
size = None
self._stack: Deque[weakref.ReferenceType[browsertab.AbstractTab]] = (
self._stack: collections.deque[weakref.ReferenceType[browsertab.AbstractTab]] = (
collections.deque(maxlen=size))
# Items that have been removed from the primary stack.
self._stack_deleted: List[weakref.ReferenceType[browsertab.AbstractTab]] = []
self._stack_deleted: list[weakref.ReferenceType[browsertab.AbstractTab]] = []
self._ignore_next = False
self._keep_deleted_next = False
@ -236,7 +236,7 @@ class TabbedBrowser(QWidget):
self.search_text = None
self.search_options: Mapping[str, Any] = {}
self._local_marks: MutableMapping[QUrl, MutableMapping[str, QPoint]] = {}
self._global_marks: MutableMapping[str, Tuple[QPoint, QUrl]] = {}
self._global_marks: MutableMapping[str, tuple[QPoint, QUrl]] = {}
self.default_window_icon = self._window().windowIcon()
self.is_private = private
self.tab_deque = TabDeque()

View File

@ -7,7 +7,7 @@
import functools
import contextlib
import dataclasses
from typing import Optional, Dict, Any
from typing import Optional, Any
from qutebrowser.qt.core import (pyqtSignal, pyqtSlot, Qt, QSize, QRect, QPoint,
QTimer, QUrl)
@ -169,7 +169,7 @@ class TabWidget(QTabWidget):
page_title = self.page_title(idx)
fields: Dict[str, Any] = {}
fields: dict[str, Any] = {}
fields['id'] = tab.tab_id
fields['current_title'] = page_title
fields['title_sep'] = ' - ' if page_title else ''

View File

@ -13,7 +13,7 @@ import shutil
import os.path
import argparse
import dataclasses
from typing import Any, Optional, Tuple
from typing import Any, Optional
from collections.abc import Sequence
from qutebrowser.qt import machinery
@ -49,7 +49,7 @@ class _Button:
default: bool = False
def _other_backend(backend: usertypes.Backend) -> Tuple[usertypes.Backend, str]:
def _other_backend(backend: usertypes.Backend) -> tuple[usertypes.Backend, str]:
"""Get the other backend enum/setting for a given backend."""
other_backend = {
usertypes.Backend.QtWebKit: usertypes.Backend.QtWebEngine,

View File

@ -8,7 +8,7 @@ Used by elf.py as well as pakjoy.py.
"""
import struct
from typing import Any, IO, Tuple
from typing import Any, IO
class ParseError(Exception):
@ -16,7 +16,7 @@ class ParseError(Exception):
"""Raised when the file can't be parsed."""
def unpack(fmt: str, fobj: IO[bytes]) -> Tuple[Any, ...]:
def unpack(fmt: str, fobj: IO[bytes]) -> tuple[Any, ...]:
"""Unpack the given struct format from the given file."""
size = struct.calcsize(fmt)
data = safe_read(fobj, size)

View File

@ -13,7 +13,6 @@ import fnmatch
import traceback
import datetime
import enum
from typing import List, Tuple
from qutebrowser.qt.core import pyqtSlot, Qt, QSize
from qutebrowser.qt.widgets import (QDialog, QLabel, QTextEdit, QPushButton,
@ -103,7 +102,7 @@ class _CrashDialog(QDialog):
super().__init__(parent)
# We don't set WA_DeleteOnClose here as on an exception, we'll get
# closed anyways, and it only could have unintended side-effects.
self._crash_info: List[Tuple[str, str]] = []
self._crash_info: list[tuple[str, str]] = []
self._btn_box = None
self._paste_text = None
self.setWindowTitle("Whoops!")

View File

@ -15,7 +15,7 @@ import functools
import threading
import faulthandler
import dataclasses
from typing import TYPE_CHECKING, Optional, cast, List
from typing import TYPE_CHECKING, Optional, cast
from collections.abc import MutableMapping
from qutebrowser.qt.core import (pyqtSlot, qInstallMessageHandler, QObject,
@ -36,8 +36,8 @@ class ExceptionInfo:
"""Information stored when there was an exception."""
pages: List[List[str]]
cmd_history: List[str]
pages: list[list[str]]
cmd_history: list[str]
objects: str

View File

@ -49,7 +49,7 @@ import re
import dataclasses
import mmap
import pathlib
from typing import IO, ClassVar, Dict, Optional, cast
from typing import IO, ClassVar, Optional, cast
from qutebrowser.qt import machinery
from qutebrowser.utils import log, version, qtutils
@ -131,7 +131,7 @@ class Header:
shnum: int
shstrndx: int
_FORMATS: ClassVar[Dict[Bitness, str]] = {
_FORMATS: ClassVar[dict[Bitness, str]] = {
Bitness.x64: '<HHIQQQIHHHHHH',
Bitness.x32: '<HHIIIIIHHHHHH',
}
@ -162,7 +162,7 @@ class SectionHeader:
addralign: int
entsize: int
_FORMATS: ClassVar[Dict[Bitness, str]] = {
_FORMATS: ClassVar[dict[Bitness, str]] = {
Bitness.x64: '<IIQQQQIIQQ',
Bitness.x32: '<IIIIIIIIII',
}

View File

@ -9,7 +9,7 @@ import locale
import shlex
import shutil
import signal
from typing import Dict, Optional
from typing import Optional
from collections.abc import Mapping, Sequence
from qutebrowser.qt.core import (pyqtSlot, pyqtSignal, QObject, QProcess,
@ -20,7 +20,7 @@ from qutebrowser.api import cmdutils, apitypes
from qutebrowser.completion.models import miscmodels
all_processes: Dict[int, Optional['GUIProcess']] = {}
all_processes: dict[int, Optional['GUIProcess']] = {}
last_pid: Optional[int] = None

View File

@ -7,7 +7,7 @@
This entire file is a giant WORKAROUND for https://bugreports.qt.io/browse/QTBUG-114334.
"""
from typing import Tuple, Union, cast, Optional
from typing import Union, cast, Optional
import enum
import ctypes
import ctypes.util
@ -138,7 +138,7 @@ class NativeEventFilter(QAbstractNativeEventFilter):
def nativeEventFilter(
self, evtype: Union[bytes, QByteArray], message: Optional[sip.voidptr]
) -> Tuple[bool, _PointerRetType]:
) -> tuple[bool, _PointerRetType]:
"""Handle XCB events."""
# We're only installed when the platform plugin is xcb
assert evtype == b"xcb_generic_event_t", evtype

View File

@ -8,7 +8,7 @@
# earlyinit.
import argparse
from typing import TYPE_CHECKING, Any, Dict, Set, Union, cast
from typing import TYPE_CHECKING, Any, Union, cast
if TYPE_CHECKING:
from qutebrowser import app
@ -29,7 +29,7 @@ class NoBackend:
backend: Union['usertypes.Backend', NoBackend] = NoBackend()
commands: Dict[str, 'command.Command'] = {}
debug_flags: Set[str] = set()
commands: dict[str, 'command.Command'] = {}
debug_flags: set[str] = set()
args = cast(argparse.Namespace, None)
qapp = cast('app.Application', None)

View File

@ -30,7 +30,7 @@ import shutil
import pathlib
import dataclasses
import contextlib
from typing import ClassVar, IO, Optional, Dict, Tuple
from typing import ClassVar, IO, Optional
from collections.abc import Iterator
from qutebrowser.config import config
@ -129,7 +129,7 @@ class PakParser:
return data
def _read_header(self) -> Dict[int, PakEntry]:
def _read_header(self) -> dict[int, PakEntry]:
"""Read the header and entry index from the .pak file."""
entries = []
@ -148,7 +148,7 @@ class PakParser:
return {entry.resource_id: entry for entry in entries}
def _find_manifest(self, entries: Dict[int, PakEntry]) -> Tuple[PakEntry, bytes]:
def _find_manifest(self, entries: dict[int, PakEntry]) -> tuple[PakEntry, bytes]:
to_check = list(entries.values())
for hangouts_id in HANGOUTS_IDS:
if hangouts_id in entries:

View File

@ -9,7 +9,7 @@ import collections
import contextlib
import dataclasses
import types
from typing import Any, Dict, List, Optional, Type, Union
from typing import Any, Optional, Union
from collections.abc import Iterator, Mapping, MutableSequence
from qutebrowser.qt.core import QObject, pyqtSignal
@ -227,8 +227,8 @@ class Database:
"""Return a Query instance linked to this Database."""
return Query(self, querystr, forward_only)
def table(self, name: str, fields: List[str],
constraints: Optional[Dict[str, str]] = None,
def table(self, name: str, fields: list[str],
constraints: Optional[dict[str, str]] = None,
parent: Optional[QObject] = None) -> 'SqlTable':
"""Return a SqlTable instance linked to this Database."""
return SqlTable(self, name, fields, constraints, parent)
@ -277,7 +277,7 @@ class Transaction(contextlib.AbstractContextManager): # type: ignore[type-arg]
raise_sqlite_error(msg, error)
def __exit__(self,
_exc_type: Optional[Type[BaseException]],
_exc_type: Optional[type[BaseException]],
exc_val: Optional[BaseException],
_exc_tb: Optional[types.TracebackType]) -> None:
db = self._database.qt_database()
@ -314,7 +314,7 @@ class Query:
ok = self.query.prepare(querystr)
self._check_ok('prepare', ok)
self.query.setForwardOnly(forward_only)
self._placeholders: List[str] = []
self._placeholders: list[str] = []
def __iter__(self) -> Iterator[Any]:
if not self.query.isActive():
@ -349,7 +349,7 @@ class Query:
if None in values:
raise BugError("Missing bound values!")
def _bind_values(self, values: Mapping[str, Any]) -> Dict[str, Any]:
def _bind_values(self, values: Mapping[str, Any]) -> dict[str, Any]:
self._placeholders = list(values)
for key, val in values.items():
self.query.bindValue(f':{key}', val)
@ -405,7 +405,7 @@ class Query:
assert rows != -1
return rows
def bound_values(self) -> Dict[str, Any]:
def bound_values(self) -> dict[str, Any]:
return {
f":{key}": self.query.boundValue(f":{key}")
for key in self._placeholders
@ -427,8 +427,8 @@ class SqlTable(QObject):
changed = pyqtSignal()
database: Database
def __init__(self, database: Database, name: str, fields: List[str],
constraints: Optional[Dict[str, str]] = None,
def __init__(self, database: Database, name: str, fields: list[str],
constraints: Optional[dict[str, str]] = None,
parent: Optional[QObject] = None) -> None:
"""Wrapper over a table in the SQL database.
@ -443,7 +443,7 @@ class SqlTable(QObject):
self.database = database
self._create_table(fields, constraints)
def _create_table(self, fields: List[str], constraints: Optional[Dict[str, str]],
def _create_table(self, fields: list[str], constraints: Optional[dict[str, str]],
*, force: bool = False) -> None:
"""Create the table if the database is uninitialized.

View File

@ -30,7 +30,7 @@ import argparse
import warnings
import importlib
import dataclasses
from typing import Optional, Dict
from typing import Optional
from qutebrowser.utils import log
@ -106,7 +106,7 @@ class SelectionInfo:
"""Information about outcomes of importing Qt wrappers."""
wrapper: Optional[str] = None
outcomes: Dict[str, str] = dataclasses.field(default_factory=dict)
outcomes: dict[str, str] = dataclasses.field(default_factory=dict)
reason: SelectionReason = SelectionReason.unknown
def set_module_error(self, name: str, error: Exception) -> None:

View File

@ -12,7 +12,7 @@ import functools
import datetime
import types
from typing import (
Any, Callable, List, Optional, Type, Union)
Any, Callable, Optional, Union)
from collections.abc import Mapping, MutableSequence, Sequence
from qutebrowser.qt.core import Qt, QEvent, QMetaMethod, QObject, pyqtBoundSignal
@ -22,7 +22,7 @@ from qutebrowser.misc import objects
from qutebrowser.qt import sip, machinery
def log_events(klass: Type[QObject]) -> Type[QObject]:
def log_events(klass: type[QObject]) -> type[QObject]:
"""Class decorator to log Qt events."""
old_event = klass.event
@ -39,7 +39,7 @@ def log_events(klass: Type[QObject]) -> Type[QObject]:
return klass
def log_signals(obj: Union[QObject, Type[QObject]]) -> Union[QObject, Type[QObject]]:
def log_signals(obj: Union[QObject, type[QObject]]) -> Union[QObject, type[QObject]]:
"""Log all signals of an object or class.
Can be used as class decorator.
@ -95,7 +95,7 @@ else:
def _qenum_key_python(
value: _EnumValueType,
klass: Type[_EnumValueType],
klass: type[_EnumValueType],
) -> Optional[str]:
"""New-style PyQt6: Try getting value from Python enum."""
if isinstance(value, enum.Enum) and value.name:
@ -115,9 +115,9 @@ def _qenum_key_python(
def _qenum_key_qt(
base: Type[sip.simplewrapper],
base: type[sip.simplewrapper],
value: _EnumValueType,
klass: Type[_EnumValueType],
klass: type[_EnumValueType],
) -> Optional[str]:
# On PyQt5, or PyQt6 with int passed: Try to ask Qt's introspection.
# However, not every Qt enum value has a staticMetaObject
@ -140,9 +140,9 @@ def _qenum_key_qt(
def qenum_key(
base: Type[sip.simplewrapper],
base: type[sip.simplewrapper],
value: _EnumValueType,
klass: Type[_EnumValueType] = None,
klass: type[_EnumValueType] = None,
) -> str:
"""Convert a Qt Enum value to its key as a string.
@ -174,9 +174,9 @@ def qenum_key(
return '0x{:04x}'.format(int(value)) # type: ignore[arg-type]
def qflags_key(base: Type[sip.simplewrapper],
def qflags_key(base: type[sip.simplewrapper],
value: _EnumValueType,
klass: Type[_EnumValueType] = None) -> str:
klass: type[_EnumValueType] = None) -> str:
"""Convert a Qt QFlags value to its keys as string.
Note: Passing a combined value (such as Qt.AlignmentFlag.AlignCenter) will get the names
@ -326,7 +326,7 @@ class log_time: # noqa: N801,N806 pylint: disable=invalid-name
self._started = datetime.datetime.now()
def __exit__(self,
_exc_type: Optional[Type[BaseException]],
_exc_type: Optional[type[BaseException]],
_exc_val: Optional[BaseException],
_exc_tb: Optional[types.TracebackType]) -> None:
assert self._started is not None
@ -373,7 +373,7 @@ def get_all_objects(start_obj: QObject = None) -> str:
if start_obj is None:
start_obj = objects.qapp
pyqt_lines: List[str] = []
pyqt_lines: list[str] = []
_get_pyqt_objects(pyqt_lines, start_obj)
pyqt_lines = [' ' + e for e in pyqt_lines]
pyqt_lines.insert(0, 'Qt objects - {} objects:'.format(len(pyqt_lines)))

View File

@ -10,7 +10,7 @@ import inspect
import os.path
import collections
import enum
from typing import Any, Callable, Optional, List, Union
from typing import Any, Callable, Optional, Union
from collections.abc import MutableMapping
import qutebrowser
@ -82,10 +82,10 @@ class DocstringParser:
"""
self._state = self.State.short
self._cur_arg_name: Optional[str] = None
self._short_desc_parts: List[str] = []
self._long_desc_parts: List[str] = []
self._short_desc_parts: list[str] = []
self._long_desc_parts: list[str] = []
self.arg_descs: MutableMapping[
str, Union[str, List[str]]] = collections.OrderedDict()
str, Union[str, list[str]]] = collections.OrderedDict()
doc = inspect.getdoc(func)
handlers = {
self.State.short: self._parse_short,

View File

@ -10,7 +10,7 @@ import posixpath
import functools
import contextlib
import html
from typing import Any, Callable, FrozenSet, List, Set, Tuple
from typing import Any, Callable
from collections.abc import Iterator
import jinja2
@ -55,7 +55,7 @@ class Loader(jinja2.BaseLoader):
self,
_env: jinja2.Environment,
template: str
) -> Tuple[str, str, Callable[[], bool]]:
) -> tuple[str, str, Callable[[], bool]]:
path = os.path.join(self._subdir, template)
try:
source = resources.read_file(path)
@ -129,10 +129,10 @@ js_environment = jinja2.Environment(loader=Loader('javascript'))
@debugcachestats.register()
@functools.lru_cache
def template_config_variables(template: str) -> FrozenSet[str]:
def template_config_variables(template: str) -> frozenset[str]:
"""Return the config variables used in the template."""
unvisted_nodes: List[jinja2.nodes.Node] = [environment.parse(template)]
result: Set[str] = set()
unvisted_nodes: list[jinja2.nodes.Node] = [environment.parse(template)]
result: set[str] = set()
while unvisted_nodes:
node = unvisted_nodes.pop()
if not isinstance(node, jinja2.nodes.Getattr):
@ -141,7 +141,7 @@ def template_config_variables(template: str) -> FrozenSet[str]:
# List of attribute names in reverse order.
# For example it's ['ab', 'c', 'd'] for 'conf.d.c.ab'.
attrlist: List[str] = []
attrlist: list[str] = []
while isinstance(node, jinja2.nodes.Getattr):
attrlist.append(node.attr)
node = node.node

View File

@ -16,7 +16,7 @@ import json
import inspect
import argparse
from typing import (TYPE_CHECKING, Any,
Optional, Set, Tuple, Union, TextIO, Literal, cast)
Optional, Union, TextIO, Literal, cast)
from collections.abc import Iterator, Mapping, MutableSequence
# NOTE: This is a Qt-free zone! All imports related to Qt logging should be done in
@ -241,7 +241,7 @@ def _init_handlers(
force_color: bool,
json_logging: bool,
ram_capacity: int
) -> Tuple[Optional["logging.StreamHandler[TextIO]"], Optional['RAMHandler']]:
) -> tuple[Optional["logging.StreamHandler[TextIO]"], Optional['RAMHandler']]:
"""Init log handlers.
Args:
@ -295,7 +295,7 @@ def _init_formatters(
color: bool,
force_color: bool,
json_logging: bool,
) -> Tuple[
) -> tuple[
Union['JSONFormatter', 'ColoredFormatter', None],
'ColoredFormatter',
'HTMLFormatter',
@ -397,7 +397,7 @@ class InvalidLogFilterError(Exception):
"""Raised when an invalid filter string is passed to LogFilter.parse()."""
def __init__(self, names: Set[str]):
def __init__(self, names: set[str]):
invalid = names - set(LOGGER_NAMES)
super().__init__("Invalid log category {} - valid categories: {}"
.format(', '.join(sorted(invalid)),
@ -418,7 +418,7 @@ class LogFilter(logging.Filter):
than debug.
"""
def __init__(self, names: Set[str], *, negated: bool = False,
def __init__(self, names: set[str], *, negated: bool = False,
only_debug: bool = True) -> None:
super().__init__()
self.names = names

View File

@ -10,7 +10,7 @@
import dataclasses
import traceback
from typing import Any, Callable, List, Union, Optional
from typing import Any, Callable, Union, Optional
from collections.abc import Iterable
from qutebrowser.qt.core import pyqtSignal, pyqtBoundSignal, QObject
@ -240,7 +240,7 @@ class GlobalMessageBridge(QObject):
def __init__(self, parent: QObject = None) -> None:
super().__init__(parent)
self._connected = False
self._cache: List[MessageInfo] = []
self._cache: list[MessageInfo] = []
def ask(self, question: usertypes.Question,
blocking: bool, *,

View File

@ -19,7 +19,7 @@ import pathlib
import operator
import contextlib
from typing import (Any, TYPE_CHECKING, BinaryIO, IO, Literal,
Optional, Union, Tuple, Protocol, cast, overload, TypeVar)
Optional, Union, Protocol, cast, overload, TypeVar)
from collections.abc import Iterator
from qutebrowser.qt import machinery, sip
@ -34,7 +34,6 @@ except ImportError: # pragma: no cover
if TYPE_CHECKING:
from qutebrowser.qt.webkit import QWebHistory
from qutebrowser.qt.webenginecore import QWebEngineHistory
from typing_extensions import TypeGuard # added in Python 3.10
from qutebrowser.misc import objects
from qutebrowser.utils import usertypes, utils
@ -532,7 +531,7 @@ class EventLoop(QEventLoop):
def _get_color_percentage(x1: int, y1: int, z1: int, a1: int,
x2: int, y2: int, z2: int, a2: int,
percent: int) -> Tuple[int, int, int, int]:
percent: int) -> tuple[int, int, int, int]:
"""Get a color which is percent% interpolated between start and end.
Args:

View File

@ -10,7 +10,7 @@ import contextlib
import posixpath
import pathlib
import importlib.resources
from typing import Union, Dict
from typing import Union
from collections.abc import Iterator, Iterable
if sys.version_info >= (3, 11): # pragma: no cover
@ -20,8 +20,8 @@ else:
from importlib.abc import Traversable
import qutebrowser
_cache: Dict[str, str] = {}
_bin_cache: Dict[str, bytes] = {}
_cache: dict[str, str] = {}
_bin_cache: dict[str, bytes] = {}
_ResourceType = Union[Traversable, pathlib.Path]

View File

@ -11,7 +11,7 @@ import contextlib
import enum
import argparse
import tempfile
from typing import Optional, Dict
from typing import Optional
from collections.abc import Iterator
from qutebrowser.qt.core import QStandardPaths
@ -20,7 +20,7 @@ from qutebrowser.qt.widgets import QApplication
from qutebrowser.utils import log, debug, utils, version, qtutils
# The cached locations
_locations: Dict["_Location", str] = {}
_locations: dict["_Location", str] = {}
class _Location(enum.Enum):

View File

@ -17,7 +17,7 @@ https://chromium.googlesource.com/chromium/src/+/6f4a6681eae01c2036336c18b06303e
import ipaddress
import fnmatch
import urllib.parse
from typing import Any, Optional, Tuple
from typing import Any, Optional
from qutebrowser.qt.core import QUrl
@ -89,7 +89,7 @@ class UrlPattern:
self._init_path(parsed)
self._init_port(parsed)
def _to_tuple(self) -> Tuple[
def _to_tuple(self) -> tuple[
bool, # _match_all
bool, # _match_subdomains
Optional[str], # _scheme

View File

@ -11,7 +11,7 @@ import ipaddress
import posixpath
import urllib.parse
import mimetypes
from typing import Optional, Tuple, Union, cast
from typing import Optional, Union, cast
from collections.abc import Iterable
from qutebrowser.qt import machinery
@ -112,7 +112,7 @@ class InvalidUrlError(Error):
super().__init__(self.msg)
def _parse_search_term(s: str) -> Tuple[Optional[str], Optional[str]]:
def _parse_search_term(s: str) -> tuple[Optional[str], Optional[str]]:
"""Get a search engine name and search term from a string.
Args:
@ -465,7 +465,7 @@ def filename_from_url(url: QUrl, fallback: str = None) -> Optional[str]:
return fallback
HostTupleType = Tuple[str, str, int]
HostTupleType = tuple[str, str, int]
def host_tuple(url: QUrl) -> HostTupleType:

View File

@ -20,7 +20,7 @@ import shlex
import sysconfig
import mimetypes
from typing import (Any, Callable, IO,
Optional, Tuple, List, Type, Union,
Optional, Union,
TypeVar, Protocol)
from collections.abc import Iterator, Sequence
@ -408,7 +408,7 @@ def qualname(obj: Any) -> str:
return repr(obj)
_ExceptionType = Union[Type[BaseException], Tuple[Type[BaseException]]]
_ExceptionType = Union[type[BaseException], tuple[type[BaseException]]]
def raises(exc: _ExceptionType, func: Callable[..., Any], *args: Any) -> bool:
@ -847,7 +847,7 @@ def parse_point(s: str) -> QPoint:
raise ValueError(e)
def match_globs(patterns: List[str], value: str) -> Optional[str]:
def match_globs(patterns: list[str], value: str) -> Optional[str]:
"""Match a list of glob-like patterns against a value.
Return:

View File

@ -19,7 +19,7 @@ import getpass
import functools
import dataclasses
import importlib.metadata
from typing import (Optional, Tuple, ClassVar, Dict, Any,
from typing import (Optional, ClassVar, Any,
TYPE_CHECKING)
from collections.abc import Mapping, Sequence
@ -106,7 +106,7 @@ class Distribution(enum.Enum):
solus = enum.auto()
def _parse_os_release() -> Optional[Dict[str, str]]:
def _parse_os_release() -> Optional[dict[str, str]]:
"""Parse an /etc/os-release file."""
filename = os.environ.get('QUTE_FAKE_OS_RELEASE', '/etc/os-release')
info = {}
@ -251,7 +251,7 @@ def _git_str_subprocess(gitpath: str) -> Optional[str]:
return None
def _release_info() -> Sequence[Tuple[str, str]]:
def _release_info() -> Sequence[tuple[str, str]]:
"""Try to gather distribution release information.
Return:
@ -380,7 +380,7 @@ class ModuleInfo:
return text
def _create_module_info() -> Dict[str, ModuleInfo]:
def _create_module_info() -> dict[str, ModuleInfo]:
packages = [
('colorama', ['VERSION', '__version__']),
('jinja2', ['__version__']),
@ -539,7 +539,7 @@ class WebEngineVersions:
chromium_security: Optional[str] = None
chromium_major: Optional[int] = dataclasses.field(init=False)
_BASES: ClassVar[Dict[int, str]] = {
_BASES: ClassVar[dict[int, str]] = {
83: '83.0.4103.122', # ~2020-06-24
87: '87.0.4280.144', # ~2020-12-02
90: '90.0.4430.228', # 2021-06-22
@ -552,7 +552,7 @@ class WebEngineVersions:
122: '122.0.6261.171', # ~2024-??-??
}
_CHROMIUM_VERSIONS: ClassVar[Dict[utils.VersionNumber, Tuple[str, Optional[str]]]] = {
_CHROMIUM_VERSIONS: ClassVar[dict[utils.VersionNumber, tuple[str, Optional[str]]]] = {
# ====== UNSUPPORTED =====
# Qt 5.12: Chromium 69
@ -708,7 +708,7 @@ class WebEngineVersions:
def _infer_chromium_version(
cls,
pyqt_webengine_version: utils.VersionNumber,
) -> Tuple[Optional[str], Optional[str]]:
) -> tuple[Optional[str], Optional[str]]:
"""Infer the Chromium version based on the PyQtWebEngine version.
Returns:
@ -1018,7 +1018,7 @@ class OpenGLInfo:
version_str: Optional[str] = None
# The parsed version as a (major, minor) tuple of ints
version: Optional[Tuple[int, ...]] = None
version: Optional[tuple[int, ...]] = None
# The vendor specific information following the version number
vendor_specific: Optional[str] = None

View File

@ -20,7 +20,7 @@ import platform
import collections
import dataclasses
import re
from typing import List, Optional
from typing import Optional
from collections.abc import Iterable
try:
@ -271,7 +271,7 @@ def build_mac(
qt5: bool,
skip_packaging: bool,
debug: bool,
) -> List[Artifact]:
) -> list[Artifact]:
"""Build macOS .dmg/.app."""
utils.print_title("Cleaning up...")
for f in ['wc.dmg', 'template.dmg']:
@ -359,7 +359,7 @@ def _build_windows_single(
qt5: bool,
skip_packaging: bool,
debug: bool,
) -> List[Artifact]:
) -> list[Artifact]:
"""Build on Windows for a single build type."""
utils.print_title("Running pyinstaller")
dist_path = pathlib.Path("dist")
@ -398,7 +398,7 @@ def build_windows(
skip_packaging: bool,
qt5: bool,
debug: bool,
) -> List[Artifact]:
) -> list[Artifact]:
"""Build windows executables/setups."""
utils.print_title("Updating 3rdparty content")
update_3rdparty.run(nsis=True, ace=False, pdfjs=True, legacy_pdfjs=qt5,
@ -423,7 +423,7 @@ def _package_windows_single(
out_path: pathlib.Path,
debug: bool,
qt5: bool,
) -> List[Artifact]:
) -> list[Artifact]:
"""Build the given installer/zip for windows."""
artifacts = []
@ -476,7 +476,7 @@ def _package_windows_single(
return artifacts
def build_sdist() -> List[Artifact]:
def build_sdist() -> list[Artifact]:
"""Build an sdist and list the contents."""
utils.print_title("Building sdist")
@ -566,7 +566,7 @@ def read_github_token(
def github_upload(
artifacts: List[Artifact],
artifacts: list[Artifact],
tag: str,
gh_token: str,
experimental: bool,
@ -644,7 +644,7 @@ def github_upload(
break
def pypi_upload(artifacts: List[Artifact], experimental: bool) -> None:
def pypi_upload(artifacts: list[Artifact], experimental: bool) -> None:
"""Upload the given artifacts to PyPI using twine."""
# https://blog.pypi.org/posts/2023-05-23-removing-pgp/
artifacts = [a for a in artifacts if a.mimetype != 'application/pgp-signature']
@ -656,13 +656,13 @@ def pypi_upload(artifacts: List[Artifact], experimental: bool) -> None:
run_twine('upload', artifacts)
def twine_check(artifacts: List[Artifact]) -> None:
def twine_check(artifacts: list[Artifact]) -> None:
"""Check packages using 'twine check'."""
utils.print_title("Running twine check...")
run_twine('check', artifacts, '--strict')
def run_twine(command: str, artifacts: List[Artifact], *args: str) -> None:
def run_twine(command: str, artifacts: list[Artifact], *args: str) -> None:
paths = [a.path for a in artifacts]
subprocess.run([sys.executable, '-m', 'twine', command, *args, *paths], check=True)

View File

@ -15,7 +15,7 @@ import subprocess
import tokenize
import traceback
import pathlib
from typing import List, Optional, Tuple
from typing import Optional
from collections.abc import Iterator
REPO_ROOT = pathlib.Path(__file__).resolve().parents[2]
@ -31,7 +31,7 @@ BINARY_EXTS = {'.png', '.icns', '.ico', '.bmp', '.gz', '.bin', '.pdf',
def _get_files(
*,
verbose: bool,
ignored: List[pathlib.Path] = None
ignored: list[pathlib.Path] = None
) -> Iterator[pathlib.Path]:
"""Iterate over all files and yield filenames."""
filenames = subprocess.run(
@ -143,8 +143,8 @@ def _check_spelling_file(path, fobj, patterns):
def _check_spelling_all(
args: argparse.Namespace,
ignored: List[pathlib.Path],
patterns: List[Tuple[re.Pattern, str]],
ignored: list[pathlib.Path],
patterns: list[tuple[re.Pattern, str]],
) -> Optional[bool]:
try:
ok = True

View File

@ -17,7 +17,7 @@ import shutil
import venv as pyvenv
import subprocess
import platform
from typing import List, Tuple, Dict, Union
from typing import Union
sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir))
from scripts import utils, link_pyqt
@ -49,7 +49,7 @@ def print_command(*cmd: Union[str, pathlib.Path], venv: bool) -> None:
utils.print_col(prefix + ' '.join([str(e) for e in cmd]), 'blue')
def parse_args(argv: List[str] = None) -> argparse.Namespace:
def parse_args(argv: list[str] = None) -> argparse.Namespace:
"""Parse commandline arguments."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--update',
@ -105,7 +105,7 @@ def _version_key(v):
return (999,)
def pyqt_versions() -> List[str]:
def pyqt_versions() -> list[str]:
"""Get a list of all available PyQt versions.
The list is based on the filenames of misc/requirements/ files.
@ -276,7 +276,7 @@ def install_pyqt_wheels(venv_dir: pathlib.Path,
pip_install(venv_dir, *wheels)
def install_pyqt_snapshot(venv_dir: pathlib.Path, packages: List[str]) -> None:
def install_pyqt_snapshot(venv_dir: pathlib.Path, packages: list[str]) -> None:
"""Install PyQt packages from the snapshot server."""
utils.print_title("Installing PyQt snapshots")
pip_install(venv_dir, '-U', *packages, '--no-deps', '--pre',
@ -348,9 +348,9 @@ def apply_xcb_util_workaround(
link_path.symlink_to(libxcb_util_path)
def _find_libs() -> Dict[Tuple[str, str], List[str]]:
def _find_libs() -> dict[tuple[str, str], list[str]]:
"""Find all system-wide .so libraries."""
all_libs: Dict[Tuple[str, str], List[str]] = {}
all_libs: dict[tuple[str, str], list[str]] = {}
if pathlib.Path("/sbin/ldconfig").exists():
# /sbin might not be in PATH on e.g. Debian

View File

@ -4,7 +4,6 @@
import dataclasses
import itertools
from typing import Dict, List
from qutebrowser.qt.core import QObject, QByteArray, QUrl, pyqtSlot
from qutebrowser.qt.gui import QImage
@ -43,7 +42,7 @@ class TestNotificationServer(QObject):
self._bus = QDBusConnection.sessionBus()
self._message_id_gen = itertools.count(1)
# A dict mapping notification IDs to currently-displayed notifications.
self.messages: Dict[int, NotificationProperties] = {}
self.messages: dict[int, NotificationProperties] = {}
self.supports_body_markup = True
self.last_id = None
@ -195,7 +194,7 @@ class TestNotificationServer(QObject):
return message_id
@pyqtSlot(QDBusMessage, result="QStringList")
def GetCapabilities(self, message: QDBusMessage) -> List[str]:
def GetCapabilities(self, message: QDBusMessage) -> list[str]:
assert not message.signature()
assert not message.arguments()
assert message.type() == QDBusMessage.MessageType.MethodCallMessage

View File

@ -7,7 +7,6 @@
import pathlib
import dataclasses
from typing import List
import pytest
import bs4
@ -97,8 +96,8 @@ class Parsed:
path: str
parent: str
folders: List[str]
files: List[str]
folders: list[str]
files: list[str]
@dataclasses.dataclass

View File

@ -6,7 +6,7 @@
"""Fake objects/stubs."""
from typing import Any, Callable, Tuple
from typing import Any, Callable
from unittest import mock
import contextlib
import shutil
@ -327,7 +327,7 @@ class FakeCommand:
completion: Any = None
maxsplit: int = None
takes_count: Callable[[], bool] = lambda: False
modes: Tuple[usertypes.KeyMode] = (usertypes.KeyMode.normal, )
modes: tuple[usertypes.KeyMode] = (usertypes.KeyMode.normal, )
class FakeTimer(QObject):

View File

@ -7,7 +7,7 @@
import logging
import itertools
import inspect
from typing import List, Dict, Any, Optional, TYPE_CHECKING
from typing import Any, Optional, TYPE_CHECKING
import pytest
from qutebrowser.qt.core import pyqtSignal, pyqtSlot, QUrl, QObject
@ -36,7 +36,7 @@ class FakeDBusMessage:
self._type = typ
self._error_name = error_name
def arguments(self) -> List[Any]:
def arguments(self) -> list[Any]:
return self._arguments
def signature(self) -> str:
@ -107,8 +107,8 @@ class FakeDBusInterface:
icon: str,
title: str,
body: str,
actions: List[str],
hints: Dict[str, Any],
actions: list[str],
hints: dict[str, Any],
timeout: int,
) -> FakeDBusMessage:
assert self.notify_reply is not None

View File

@ -4,7 +4,6 @@
import logging
from typing import List, Tuple
import pytest
QWebEngineSettings = pytest.importorskip("qutebrowser.qt.webenginecore").QWebEngineSettings
@ -70,7 +69,7 @@ class TestDefinition:
) -> darkmode._Definition:
return darkmode._Definition(setting1, setting2, mandatory=set(), prefix="")
def _get_settings(self, definition: darkmode._Definition) -> List[darkmode._Setting]:
def _get_settings(self, definition: darkmode._Definition) -> list[darkmode._Setting]:
return [setting for _key, setting in definition.prefixed_settings()]
@pytest.mark.parametrize("prefix", ["", "prefix"])
@ -365,7 +364,7 @@ def test_customization(config_stub, setting, value, exp_key, exp_val):
('6.5.3', 'policy.images', 'smart', [('ImagePolicy', '2')]),
('6.5.3', 'policy.images', 'smart-simple', [('ImagePolicy', '2')]),
])
def test_image_policy(config_stub, qtwe_version: str, setting: str, value: str, expected: List[Tuple[str, str]]):
def test_image_policy(config_stub, qtwe_version: str, setting: str, value: str, expected: list[tuple[str, str]]):
config_stub.val.colors.webpage.darkmode.enabled = True
config_stub.set_obj('colors.webpage.darkmode.' + setting, value)

View File

@ -5,7 +5,6 @@
import os
import dataclasses
from typing import List
import pytest
import bs4
@ -101,8 +100,8 @@ class TestDirbrowserHtml:
class Parsed:
parent: str
folders: List[str]
files: List[str]
folders: list[str]
files: list[str]
@dataclasses.dataclass
class Item:

View File

@ -5,7 +5,6 @@
import pathlib
import logging
import csv
from typing import Tuple
from collections.abc import Iterable
from qutebrowser.qt.core import QUrl
@ -166,7 +165,7 @@ def assert_only_one_success_message(messages):
def assert_urls(
ad_blocker: braveadblock.BraveAdBlocker,
urls: Iterable[Tuple[str, str, ResourceType]],
urls: Iterable[tuple[str, str, ResourceType]],
should_be_blocked: bool,
) -> None:
for (str_url, source_str_url, request_type) in urls:

View File

@ -12,7 +12,7 @@ import json
import hashlib
import dataclasses
from unittest import mock
from typing import Optional, List
from typing import Optional
import pytest
from qutebrowser.qt.core import pyqtSignal, QObject
@ -631,7 +631,7 @@ class TestSendOrListen:
no_err_windows: bool
basedir: str
command: List[str]
command: list[str]
target: Optional[str]
@pytest.fixture

View File

@ -5,7 +5,6 @@
"""Tests for qutebrowser.misc.split."""
import dataclasses
from typing import List
import pytest
@ -100,8 +99,8 @@ def _parse_split_test_data_str():
class TestCase:
inp: str
keep: List[str]
no_keep: List[str]
keep: list[str]
no_keep: list[str]
for line in test_data_str.splitlines():
if not line:

View File

@ -9,7 +9,7 @@ import sys
import html
import argparse
import typing
from typing import Any, Optional, List, Dict, Union, Type
from typing import Any, Optional, Union
import dataclasses
import pytest
@ -51,7 +51,7 @@ def undo_init(monkeypatch: pytest.MonkeyPatch) -> None:
(machinery.NoWrapperAvailableError(machinery.SelectionInfo()), ImportError),
],
)
def test_importerror_exceptions(exception: Exception, base: Type[Exception]):
def test_importerror_exceptions(exception: Exception, base: type[Exception]):
with pytest.raises(base):
raise exception
@ -118,7 +118,7 @@ def test_selectioninfo_str(info: machinery.SelectionInfo, expected: str):
@pytest.mark.parametrize("order", [["PyQt5", "PyQt6"], ["PyQt6", "PyQt5"]])
def test_selectioninfo_str_wrapper_precedence(order: List[str]):
def test_selectioninfo_str_wrapper_precedence(order: list[str]):
"""The order of the wrappers should be the same as in machinery.WRAPPERS."""
info = machinery.SelectionInfo(
wrapper="PyQt6",
@ -210,7 +210,7 @@ def modules():
)
def test_autoselect(
stubs: Any,
available: Dict[str, Union[bool, Exception]],
available: dict[str, Union[bool, Exception]],
expected: machinery.SelectionInfo,
monkeypatch: pytest.MonkeyPatch,
):
@ -417,7 +417,7 @@ class TestInit:
def test_none_available_implicit(
self,
stubs: Any,
modules: Dict[str, bool],
modules: dict[str, bool],
monkeypatch: pytest.MonkeyPatch,
qt_auto_env: None,
):
@ -441,7 +441,7 @@ class TestInit:
def test_none_available_explicit(
self,
stubs: Any,
modules: Dict[str, bool],
modules: dict[str, bool],
monkeypatch: pytest.MonkeyPatch,
empty_args: argparse.Namespace,
qt_auto_env: None,