diff options
author | Florian Bruhin <me@the-compiler.org> | 2021-01-11 22:22:30 +0100 |
---|---|---|
committer | Florian Bruhin <me@the-compiler.org> | 2021-01-13 20:26:41 +0100 |
commit | c970c6335521fee359c1a68c0431c612631e73fb (patch) | |
tree | 1062d9ffd9fbfcafc0753308b8e7a15a5f5f6920 /qutebrowser | |
parent | 4b7d52ae7cdf52ebef038b4a90b9fe95ab002105 (diff) | |
download | qutebrowser-c970c6335521fee359c1a68c0431c612631e73fb.tar.gz qutebrowser-c970c6335521fee359c1a68c0431c612631e73fb.zip |
dataclasses: Initial switch
See #6023
Diffstat (limited to 'qutebrowser')
30 files changed, 225 insertions, 219 deletions
diff --git a/qutebrowser/browser/browsertab.py b/qutebrowser/browser/browsertab.py index c62c75d48..b6774e38b 100644 --- a/qutebrowser/browser/browsertab.py +++ b/qutebrowser/browser/browsertab.py @@ -25,7 +25,7 @@ import functools from typing import (cast, TYPE_CHECKING, Any, Callable, Iterable, List, Optional, Sequence, Set, Type, Union) -import attr +import dataclasses from PyQt5.QtCore import (pyqtSignal, pyqtSlot, QUrl, QObject, QSizeF, Qt, QEvent, QPoint) from PyQt5.QtGui import QKeyEvent, QIcon @@ -108,7 +108,7 @@ class TerminationStatus(enum.Enum): killed = 3 -@attr.s +@dataclasses.dataclass class TabData: """A simple namespace with a fixed set of attributes. @@ -130,17 +130,17 @@ class TabData: splitter: InspectorSplitter used to show inspector inside the tab. """ - keep_icon: bool = attr.ib(False) - viewing_source: bool = attr.ib(False) - inspector: Optional['AbstractWebInspector'] = attr.ib(None) - open_target: usertypes.ClickTarget = attr.ib(usertypes.ClickTarget.normal) - override_target: Optional[usertypes.ClickTarget] = attr.ib(None) - pinned: bool = attr.ib(False) - fullscreen: bool = attr.ib(False) - netrc_used: bool = attr.ib(False) - input_mode: usertypes.KeyMode = attr.ib(usertypes.KeyMode.normal) - last_navigation: usertypes.NavigationRequest = attr.ib(None) - splitter: miscwidgets.InspectorSplitter = attr.ib(None) + keep_icon: bool = False + viewing_source: bool = False + inspector: Optional['AbstractWebInspector'] = None + open_target: usertypes.ClickTarget = usertypes.ClickTarget.normal + override_target: Optional[usertypes.ClickTarget] = None + pinned: bool = False + fullscreen: bool = False + netrc_used: bool = False + input_mode: usertypes.KeyMode = usertypes.KeyMode.normal + last_navigation: Optional[usertypes.NavigationRequest] = None + splitter: Optional[miscwidgets.InspectorSplitter] = None def should_show_icon(self) -> bool: return (config.val.tabs.favicons.show == 'always' or diff --git a/qutebrowser/browser/greasemonkey.py b/qutebrowser/browser/greasemonkey.py index 9e25e49bd..a8fdd47ed 100644 --- a/qutebrowser/browser/greasemonkey.py +++ b/qutebrowser/browser/greasemonkey.py @@ -28,7 +28,7 @@ import glob import textwrap from typing import cast, List, Sequence -import attr +import dataclasses from PyQt5.QtCore import pyqtSignal, QObject, QUrl from qutebrowser.utils import (log, standarddir, jinja, objreg, utils, @@ -198,15 +198,15 @@ class GreasemonkeyScript: self._code = "\n".join([textwrap.indent(source, " "), self._code]) -@attr.s +@dataclasses.dataclass class MatchingScripts: """All userscripts registered to run on a particular url.""" - url = attr.ib() - start = attr.ib(default=attr.Factory(list)) - end = attr.ib(default=attr.Factory(list)) - idle = attr.ib(default=attr.Factory(list)) + 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) class GreasemonkeyMatcher: diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py index f914f3085..5a22ad61f 100644 --- a/qutebrowser/browser/hints.py +++ b/qutebrowser/browser/hints.py @@ -29,7 +29,7 @@ from string import ascii_lowercase from typing import (TYPE_CHECKING, Callable, Dict, Iterable, Iterator, List, Mapping, MutableSequence, Optional, Sequence, Set) -import attr +import dataclasses from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, Qt, QUrl from PyQt5.QtWidgets import QLabel @@ -150,7 +150,7 @@ class HintLabel(QLabel): self.deleteLater() -@attr.s +@dataclasses.dataclass class HintContext: """Context namespace used for hinting. @@ -181,20 +181,20 @@ class HintContext: group: The group of web elements to hint. """ - all_labels: List[HintLabel] = attr.ib(attr.Factory(list)) - labels: Dict[str, HintLabel] = attr.ib(attr.Factory(dict)) - target: Target = attr.ib(None) - baseurl: QUrl = attr.ib(None) - to_follow: str = attr.ib(None) - rapid: bool = attr.ib(False) - first_run: bool = attr.ib(True) - add_history: bool = attr.ib(False) - filterstr: str = attr.ib(None) - args: List[str] = attr.ib(attr.Factory(list)) - tab: 'browsertab.AbstractTab' = attr.ib(None) - group: str = attr.ib(None) - hint_mode: str = attr.ib(None) - first: bool = attr.ib(False) + all_labels: List[HintLabel] = dataclasses.field(default_factory=list) + labels: Dict[str, HintLabel] = dataclasses.field(default_factory=dict) + target: Optional[Target] = None + baseurl: Optional[QUrl] = None + to_follow: Optional[str] = None + rapid: bool = False + first_run: bool = True + add_history: bool = False + filterstr: Optional[str] = None + args: List[str] = dataclasses.field(default_factory=list) + tab: Optional['browsertab.AbstractTab'] = None + group: Optional[str] = None + hint_mode: Optional[str] = None + first: bool = False def get_args(self, urlstr: str) -> Sequence[str]: """Get the arguments, with {hint-url} replaced by the given URL.""" diff --git a/qutebrowser/browser/qtnetworkdownloads.py b/qutebrowser/browser/qtnetworkdownloads.py index 3aebbb6dd..cad575a6e 100644 --- a/qutebrowser/browser/qtnetworkdownloads.py +++ b/qutebrowser/browser/qtnetworkdownloads.py @@ -24,11 +24,11 @@ import os.path import shutil import functools from typing import Dict, IO, Optional +import dataclasses -import attr from PyQt5.QtCore import pyqtSlot, pyqtSignal, QTimer, QUrl from PyQt5.QtWidgets import QApplication -from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply +from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManager from qutebrowser.config import config, websettings from qutebrowser.utils import message, usertypes, log, urlutils, utils, debug, objreg @@ -38,11 +38,11 @@ from qutebrowser.browser.webkit import http from qutebrowser.browser.webkit.network import networkmanager -@attr.s +@dataclasses.dataclass class _RetryInfo: - request = attr.ib() - manager = attr.ib() + request: QNetworkRequest + manager: QNetworkAccessManager class DownloadItem(downloads.AbstractDownloadItem): diff --git a/qutebrowser/browser/webengine/interceptor.py b/qutebrowser/browser/webengine/interceptor.py index 8804bea6e..98798983b 100644 --- a/qutebrowser/browser/webengine/interceptor.py +++ b/qutebrowser/browser/webengine/interceptor.py @@ -19,7 +19,8 @@ """A request interceptor taking care of adblocking and custom headers.""" -import attr +import dataclasses +from typing import Optional from PyQt5.QtCore import QUrl, QByteArray from PyQt5.QtWebEngineCore import (QWebEngineUrlRequestInterceptor, @@ -32,29 +33,29 @@ from qutebrowser.extensions import interceptors from qutebrowser.misc import objects -@attr.s +@dataclasses.dataclass class WebEngineRequest(interceptors.Request): """QtWebEngine-specific request interceptor functionality.""" _WHITELISTED_REQUEST_METHODS = {QByteArray(b'GET'), QByteArray(b'HEAD')} - _webengine_info: QWebEngineUrlRequestInfo = attr.ib(default=None) + webengine_info: Optional[QWebEngineUrlRequestInfo] = None # FIXME private #: If this request has been redirected already - _redirected: bool = attr.ib(init=False, default=False) + _redirected: bool = dataclasses.field(init=False, default=False) def redirect(self, url: QUrl) -> None: if self._redirected: raise interceptors.RedirectException("Request already redirected.") - if self._webengine_info is None: + if self.webengine_info is None: raise interceptors.RedirectException("Request improperly initialized.") # Redirecting a request that contains payload data is not allowed. # To be safe, abort on any request not in a whitelist. - if (self._webengine_info.requestMethod() + if (self.webengine_info.requestMethod() not in self._WHITELISTED_REQUEST_METHODS): raise interceptors.RedirectException( "Request method does not support redirection.") - self._webengine_info.redirect(url) + self.webengine_info.redirect(url) self._redirected = True diff --git a/qutebrowser/browser/webkit/mhtml.py b/qutebrowser/browser/webkit/mhtml.py index 794e1b73b..bf008d009 100644 --- a/qutebrowser/browser/webkit/mhtml.py +++ b/qutebrowser/browser/webkit/mhtml.py @@ -33,9 +33,9 @@ import email.encoders import email.mime.multipart import email.message import quopri -from typing import MutableMapping, Set, Tuple +import dataclasses +from typing import MutableMapping, Set, Tuple, Callable -import attr from PyQt5.QtCore import QUrl from qutebrowser.browser import downloads @@ -44,13 +44,13 @@ from qutebrowser.utils import log, objreg, message, usertypes, utils, urlutils from qutebrowser.extensions import interceptors -@attr.s +@dataclasses.dataclass class _File: - content = attr.ib() - content_type = attr.ib() - content_location = attr.ib() - transfer_encoding = attr.ib() + content: bytes + content_type: str + content_location: str + transfer_encoding: Callable[[email.message.Message], None] _CSS_URL_PATTERNS = [re.compile(x) for x in [ diff --git a/qutebrowser/browser/webkit/network/networkmanager.py b/qutebrowser/browser/webkit/network/networkmanager.py index b56518675..9eac7fea3 100644 --- a/qutebrowser/browser/webkit/network/networkmanager.py +++ b/qutebrowser/browser/webkit/network/networkmanager.py @@ -23,9 +23,10 @@ import collections import html from typing import TYPE_CHECKING, Dict, MutableMapping, Optional, Sequence -import attr +import dataclasses from PyQt5.QtCore import pyqtSlot, pyqtSignal, QUrl, QByteArray -from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkReply, QSslSocket, QSslError +from PyQt5.QtNetwork import (QNetworkAccessManager, QNetworkReply, QSslSocket, + QSslError, QNetworkProxy) from qutebrowser.config import config from qutebrowser.utils import (message, log, usertypes, utils, objreg, @@ -46,14 +47,14 @@ HOSTBLOCK_ERROR_STRING = '%HOSTBLOCK%' _proxy_auth_cache: Dict['ProxyId', 'prompt.AuthInfo'] = {} -@attr.s(frozen=True) +@dataclasses.dataclass(frozen=True) class ProxyId: """Information identifying a proxy server.""" - type = attr.ib() - hostname = attr.ib() - port = attr.ib() + type: QNetworkProxy.ProxyType + hostname: str + port: int def _is_secure_cipher(cipher): diff --git a/qutebrowser/browser/webkit/rfc6266.py b/qutebrowser/browser/webkit/rfc6266.py index b43bfb808..10c337ee1 100644 --- a/qutebrowser/browser/webkit/rfc6266.py +++ b/qutebrowser/browser/webkit/rfc6266.py @@ -22,8 +22,9 @@ import urllib.parse import string import re +import dataclasses +from typing import Optional -import attr import pypeg2 as peg from qutebrowser.utils import utils @@ -210,13 +211,13 @@ class ContentDispositionValue: peg.optional(';')) -@attr.s +@dataclasses.dataclass class LangTagged: """A string with an associated language.""" - string = attr.ib() - langtag = attr.ib() + string: str + langtag: Optional[str] class Error(Exception): diff --git a/qutebrowser/commands/command.py b/qutebrowser/commands/command.py index 61b44d555..d8d08e50b 100644 --- a/qutebrowser/commands/command.py +++ b/qutebrowser/commands/command.py @@ -23,9 +23,8 @@ import inspect import collections import traceback import typing -from typing import Any, MutableMapping, MutableSequence, Tuple, Union - -import attr +from typing import Any, MutableMapping, MutableSequence, Tuple, Union, List, Optional +import dataclasses from qutebrowser.api import cmdutils from qutebrowser.commands import cmdexc, argparser @@ -34,17 +33,17 @@ from qutebrowser.utils import debug as debug_utils from qutebrowser.misc import objects -@attr.s +@dataclasses.dataclass class ArgInfo: """Information about an argument.""" - value = attr.ib(None) - hide = attr.ib(False) - metavar = attr.ib(None) - flag = attr.ib(None) - completion = attr.ib(None) - choices = attr.ib(None) + value: Optional[usertypes.CommandValue] = None + hide: bool = False + metavar: Optional[str] = None + flag: Optional[str] = None + completion: Any = None # FIXME + choices: List[str] = None class Command: diff --git a/qutebrowser/commands/runners.py b/qutebrowser/commands/runners.py index c195a8be9..4913f9e3e 100644 --- a/qutebrowser/commands/runners.py +++ b/qutebrowser/commands/runners.py @@ -22,9 +22,10 @@ import traceback import re import contextlib -from typing import TYPE_CHECKING, Callable, Dict, Iterator, Mapping, MutableMapping +from typing import (TYPE_CHECKING, Callable, Dict, Iterator, Mapping, MutableMapping, + List, Optional) +import dataclasses -import attr from PyQt5.QtCore import pyqtSlot, QUrl, QObject from qutebrowser.api import cmdutils @@ -42,14 +43,14 @@ _ReplacementFunction = Callable[['tabbedbrowser.TabbedBrowser'], str] last_command = {} -@attr.s +@dataclasses.dataclass class ParseResult: """The result of parsing a commandline.""" - cmd = attr.ib() - args = attr.ib() - cmdline = attr.ib() + cmd: Optional[str] + args: Optional[List[str]] + cmdline: List[str] def _url(tabbed_browser): diff --git a/qutebrowser/completion/completer.py b/qutebrowser/completion/completer.py index d66e3ee40..5b9ac2a76 100644 --- a/qutebrowser/completion/completer.py +++ b/qutebrowser/completion/completer.py @@ -19,7 +19,9 @@ """Completer attached to a CompletionView.""" -import attr +import dataclasses +from typing import Any + from PyQt5.QtCore import pyqtSlot, QObject, QTimer from qutebrowser.config import config @@ -29,15 +31,15 @@ from qutebrowser.utils import log, utils, debug, objreg from qutebrowser.completion.models import miscmodels -@attr.s +@dataclasses.dataclass class CompletionInfo: """Context passed into all completion functions.""" - config = attr.ib() - keyconf = attr.ib() - win_id = attr.ib() - cur_tab = attr.ib() + config: Any # FIXME + keyconf: Any # FIXME + win_id: int + cur_tab: Any # FIXME class Completer(QObject): diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py index 065527bb9..14e1c30ef 100644 --- a/qutebrowser/config/configdata.py +++ b/qutebrowser/config/configdata.py @@ -28,7 +28,7 @@ from typing import (Any, Dict, Iterable, List, Mapping, MutableMapping, Optional Sequence, Tuple, Union, cast) import functools -import attr +import dataclasses from qutebrowser.config import configtypes from qutebrowser.utils import usertypes, qtutils, utils from qutebrowser.misc import debugcachestats @@ -39,7 +39,7 @@ MIGRATIONS = cast('Migrations', None) _BackendDict = Mapping[str, Union[str, bool]] -@attr.s +@dataclasses.dataclass class Option: """Description of an Option in the config. @@ -47,18 +47,18 @@ class Option: Note that this is just an option which exists, with no value associated. """ - name: str = attr.ib() - typ: configtypes.BaseType = attr.ib() - default: Any = attr.ib() - backends: Iterable[usertypes.Backend] = attr.ib() - raw_backends: Optional[Mapping[str, bool]] = attr.ib() - description: str = attr.ib() - supports_pattern: bool = attr.ib(default=False) - restart: bool = attr.ib(default=False) - no_autoconfig: bool = attr.ib(default=False) + name: str + typ: configtypes.BaseType + default: Any + backends: Iterable[usertypes.Backend] + raw_backends: Optional[Mapping[str, bool]] + description: str + supports_pattern: bool = False + restart: bool = False + no_autoconfig: bool = False -@attr.s +@dataclasses.dataclass class Migrations: """Migrated options in configdata.yml. @@ -68,8 +68,8 @@ class Migrations: deleted: A list of option names which have been removed. """ - renamed: Dict[str, str] = attr.ib(default=attr.Factory(dict)) - deleted: List[str] = attr.ib(default=attr.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) -> None: diff --git a/qutebrowser/config/configexc.py b/qutebrowser/config/configexc.py index 872f777ff..c155510bd 100644 --- a/qutebrowser/config/configexc.py +++ b/qutebrowser/config/configexc.py @@ -21,7 +21,7 @@ from typing import Any, Mapping, Optional, Sequence, Union -import attr +import dataclasses from qutebrowser.utils import usertypes, log @@ -105,7 +105,7 @@ class NoOptionError(Error): self.option = option -@attr.s +@dataclasses.dataclass class ConfigErrorDesc: """A description of an error happening while reading the config. @@ -116,9 +116,9 @@ class ConfigErrorDesc: traceback: The formatted traceback of the exception. """ - text: str = attr.ib() - exception: Union[str, Exception] = attr.ib() - traceback: str = attr.ib(None) + text: str + exception: Union[str, Exception] + traceback: Optional[str] = None def __str__(self) -> str: if self.traceback: diff --git a/qutebrowser/config/configtypes.py b/qutebrowser/config/configtypes.py index 6328c3140..cc3410648 100644 --- a/qutebrowser/config/configtypes.py +++ b/qutebrowser/config/configtypes.py @@ -53,7 +53,7 @@ import json from typing import (Any, Callable, Dict as DictType, Iterable, Iterator, List as ListType, Optional, Pattern, Sequence, Tuple, Union) -import attr +import dataclasses import yaml from PyQt5.QtCore import QUrl, Qt from PyQt5.QtGui import QColor @@ -1645,15 +1645,15 @@ class FuzzyUrl(BaseType): raise configexc.ValidationError(value, str(e)) -@attr.s +@dataclasses.dataclass class PaddingValues: """Four padding values.""" - top: int = attr.ib() - bottom: int = attr.ib() - left: int = attr.ib() - right: int = attr.ib() + top: int + bottom: int + left: int + right: int class Padding(Dict): diff --git a/qutebrowser/config/websettings.py b/qutebrowser/config/websettings.py index e1cb393dc..5093c6185 100644 --- a/qutebrowser/config/websettings.py +++ b/qutebrowser/config/websettings.py @@ -24,7 +24,7 @@ import argparse import functools from typing import Any, Callable, Dict, Optional -import attr +import dataclasses from PyQt5.QtCore import QUrl, pyqtSlot, qVersion from PyQt5.QtGui import QFont @@ -36,16 +36,16 @@ from qutebrowser.misc import objects, debugcachestats UNSET = object() -@attr.s +@dataclasses.dataclass class UserAgent: """A parsed user agent.""" - os_info: str = attr.ib() - webkit_version: str = attr.ib() - upstream_browser_key: str = attr.ib() - upstream_browser_version: str = attr.ib() - qt_key: str = attr.ib() + os_info: str + webkit_version: str + upstream_browser_key: str + upstream_browser_version: str + qt_key: str @classmethod def parse(cls, ua: str) -> 'UserAgent': diff --git a/qutebrowser/extensions/interceptors.py b/qutebrowser/extensions/interceptors.py index 9c50346d7..3d7f99deb 100644 --- a/qutebrowser/extensions/interceptors.py +++ b/qutebrowser/extensions/interceptors.py @@ -22,7 +22,7 @@ import enum from typing import Callable, List, Optional -import attr +import dataclasses from PyQt5.QtCore import QUrl @@ -62,21 +62,21 @@ class RedirectException(Exception): """Raised when the request was invalid, or a request was already made.""" -@attr.s +@dataclasses.dataclass class Request: """A request which can be intercepted/blocked.""" #: The URL of the page being shown. - first_party_url: Optional[QUrl] = attr.ib() + first_party_url: Optional[QUrl] #: The URL of the file being requested. - request_url: QUrl = attr.ib() + request_url: QUrl - is_blocked: bool = attr.ib(False) + is_blocked: bool = False #: The resource type of the request. None if not supported on this backend. - resource_type: Optional[ResourceType] = attr.ib(None) + resource_type: Optional[ResourceType] = None def block(self) -> None: """Block this request.""" diff --git a/qutebrowser/extensions/loader.py b/qutebrowser/extensions/loader.py index b6d86f517..066d3b793 100644 --- a/qutebrowser/extensions/loader.py +++ b/qutebrowser/extensions/loader.py @@ -27,7 +27,7 @@ import importlib import argparse from typing import Callable, Iterator, List, Optional, Set, Tuple -import attr +import dataclasses from PyQt5.QtCore import pyqtSlot @@ -41,17 +41,17 @@ from qutebrowser.misc import objects _module_infos = [] -@attr.s +@dataclasses.dataclass class InitContext: """Context an extension gets in its init hook.""" - data_dir: pathlib.Path = attr.ib() - config_dir: pathlib.Path = attr.ib() - args: argparse.Namespace = attr.ib() + data_dir: pathlib.Path + config_dir: pathlib.Path + args: argparse.Namespace -@attr.s +@dataclasses.dataclass class ModuleInfo: """Information attached to an extension module. @@ -61,17 +61,17 @@ class ModuleInfo: _ConfigChangedHooksType = List[Tuple[Optional[str], Callable]] - skip_hooks: bool = attr.ib(False) - init_hook: Optional[Callable] = attr.ib(None) - config_changed_hooks: _ConfigChangedHooksType = attr.ib(attr.Factory(list)) + skip_hooks: bool = False + init_hook: Optional[Callable] = None + config_changed_hooks: _ConfigChangedHooksType = dataclasses.field(default_factory=list) -@attr.s +@dataclasses.dataclass class ExtensionInfo: """Information about a qutebrowser extension.""" - name: str = attr.ib() + name: str def add_module_info(module: types.ModuleType) -> ModuleInfo: diff --git a/qutebrowser/keyinput/basekeyparser.py b/qutebrowser/keyinput/basekeyparser.py index 23b77cba1..890effb17 100644 --- a/qutebrowser/keyinput/basekeyparser.py +++ b/qutebrowser/keyinput/basekeyparser.py @@ -23,7 +23,7 @@ import string import types from typing import Mapping, MutableMapping, Optional, Sequence -import attr +import dataclasses from PyQt5.QtCore import pyqtSignal, QObject, Qt from PyQt5.QtGui import QKeySequence, QKeyEvent @@ -32,16 +32,16 @@ from qutebrowser.utils import usertypes, log, utils from qutebrowser.keyinput import keyutils -@attr.s(frozen=True) +@dataclasses.dataclass(frozen=True) class MatchResult: """The result of matching a keybinding.""" - match_type: QKeySequence.SequenceMatch = attr.ib() - command: Optional[str] = attr.ib() - sequence: keyutils.KeySequence = attr.ib() + match_type: QKeySequence.SequenceMatch + command: Optional[str] + sequence: keyutils.KeySequence - def __attrs_post_init__(self) -> None: + def __post_init__(self) -> None: if self.match_type == QKeySequence.ExactMatch: assert self.command is not None else: diff --git a/qutebrowser/keyinput/keyutils.py b/qutebrowser/keyinput/keyutils.py index bc8c4a5fe..f27703110 100644 --- a/qutebrowser/keyinput/keyutils.py +++ b/qutebrowser/keyinput/keyutils.py @@ -34,7 +34,7 @@ handle what we actually think we do. import itertools from typing import cast, overload, Iterable, Iterator, List, Mapping, Optional, Union -import attr +import dataclasses from PyQt5.QtCore import Qt, QEvent from PyQt5.QtGui import QKeySequence, QKeyEvent @@ -336,7 +336,7 @@ def _parse_single_key(keystr: str) -> str: return 'Shift+' + keystr if keystr.isupper() else keystr -@attr.s(frozen=True) +@dataclasses.dataclass(frozen=True) class KeyInfo: """A key with optional modifiers. @@ -346,8 +346,8 @@ class KeyInfo: modifiers: A Qt::KeyboardModifiers enum value. """ - key: Qt.Key = attr.ib() - modifiers: _ModifierType = attr.ib() + key: Qt.Key + modifiers: _ModifierType @classmethod def from_event(cls, e: QKeyEvent) -> 'KeyInfo': diff --git a/qutebrowser/keyinput/modeman.py b/qutebrowser/keyinput/modeman.py index df5f08e2c..c40aacdd6 100644 --- a/qutebrowser/keyinput/modeman.py +++ b/qutebrowser/keyinput/modeman.py @@ -22,7 +22,7 @@ import functools from typing import Mapping, Callable, MutableMapping, Union, Set, cast -import attr +import dataclasses from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QObject, QEvent from PyQt5.QtGui import QKeyEvent @@ -40,7 +40,7 @@ PROMPT_MODES = [usertypes.KeyMode.prompt, usertypes.KeyMode.yesno] ParserDictType = MutableMapping[usertypes.KeyMode, basekeyparser.BaseKeyParser] -@attr.s(frozen=True) +@dataclasses.dataclass(frozen=True) class KeyEvent: """A small wrapper over a QKeyEvent storing its data. @@ -54,8 +54,8 @@ class KeyEvent: text: A string (QKeyEvent::text). """ - key: Qt.Key = attr.ib() - text: str = attr.ib() + key: Qt.Key + text: str @classmethod def from_event(cls, event: QKeyEvent) -> 'KeyEvent': diff --git a/qutebrowser/mainwindow/prompt.py b/qutebrowser/mainwindow/prompt.py index 85363a3fc..f214e7782 100644 --- a/qutebrowser/mainwindow/prompt.py +++ b/qutebrowser/mainwindow/prompt.py @@ -25,7 +25,7 @@ import collections import functools from typing import Deque, MutableSequence, Optional, cast -import attr +import dataclasses from PyQt5.QtCore import (pyqtSlot, pyqtSignal, Qt, QTimer, QDir, QModelIndex, QItemSelectionModel, QObject, QEventLoop) from PyQt5.QtWidgets import (QWidget, QGridLayout, QVBoxLayout, QLineEdit, @@ -43,13 +43,13 @@ from qutebrowser.utils import urlmatch prompt_queue = cast('PromptQueue', None) -@attr.s +@dataclasses.dataclass class AuthInfo: """Authentication info returned by a prompt.""" - user = attr.ib() - password = attr.ib() + user: str + password: str class Error(Exception): diff --git a/qutebrowser/mainwindow/statusbar/bar.py b/qutebrowser/mainwindow/statusbar/bar.py index 821ea030b..cb059f682 100644 --- a/qutebrowser/mainwindow/statusbar/bar.py +++ b/qutebrowser/mainwindow/statusbar/bar.py @@ -20,7 +20,7 @@ """The main statusbar widget.""" import enum -import attr +import dataclasses from PyQt5.QtCore import (pyqtSignal, pyqtSlot, # type: ignore[attr-defined] pyqtProperty, Qt, QSize, QTimer) from PyQt5.QtWidgets import QWidget, QHBoxLayout, QStackedLayout, QSizePolicy @@ -34,7 +34,7 @@ from qutebrowser.mainwindow.statusbar import (backforward, command, progress, tabindex, textbase) -@attr.s +@dataclasses.dataclass class ColorFlags: """Flags which change the appearance of the statusbar. @@ -56,12 +56,12 @@ class ColorFlags: on = enum.auto() selection = enum.auto() - prompt = attr.ib(False) - insert = attr.ib(False) - command = attr.ib(False) - caret = attr.ib(CaretMode.off) - private = attr.ib(False) - passthrough = attr.ib(False) + prompt: bool = False + insert: bool = False + command: bool = False + caret: CaretMode = CaretMode.off + private: bool = False + passthrough: bool = False def to_stringlist(self): """Get a string list of set flags used in the stylesheet. diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py index 78eb864a6..33b5708d9 100644 --- a/qutebrowser/mainwindow/tabbedbrowser.py +++ b/qutebrowser/mainwindow/tabbedbrowser.py @@ -26,7 +26,7 @@ import datetime from typing import ( Any, Deque, List, Mapping, MutableMapping, MutableSequence, Optional, Tuple) -import attr +import dataclasses from PyQt5.QtWidgets import QSizePolicy, QWidget, QApplication from PyQt5.QtCore import pyqtSignal, pyqtSlot, QTimer, QUrl @@ -39,16 +39,17 @@ from qutebrowser.utils import (log, usertypes, utils, qtutils, objreg, from qutebrowser.misc import quitter -@attr.s +@dataclasses.dataclass class _UndoEntry: """Information needed for :undo.""" - url = attr.ib() - history = attr.ib() - index = attr.ib() - pinned = attr.ib() - created_at = attr.ib(attr.Factory(datetime.datetime.now)) + url: QUrl + history: bytes # FIXME + index: int + pinned: bool + created_at: datetime.datetime = dataclasses.field( + default_factory=datetime.datetime.now) class TabDeque: diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py index 5263ecff9..7d1f0da0b 100644 --- a/qutebrowser/mainwindow/tabwidget.py +++ b/qutebrowser/mainwindow/tabwidget.py @@ -23,7 +23,7 @@ import functools import contextlib from typing import Optional, cast -import attr +import dataclasses from PyQt5.QtCore import (pyqtSignal, pyqtSlot, Qt, QSize, QRect, QPoint, QTimer, QUrl) from PyQt5.QtWidgets import (QTabWidget, QTabBar, QSizePolicy, QCommonStyle, @@ -712,7 +712,7 @@ class TabBar(QTabBar): tabbed_browser.wheelEvent(e) -@attr.s +@dataclasses.dataclass class Layouts: """Layout information for tab. @@ -720,9 +720,9 @@ class Layouts: Used by TabBarStyle._tab_layout(). """ - text = attr.ib() - icon = attr.ib() - indicator = attr.ib() + text: QRect + icon: QRect + indicator: QRect class TabBarStyle(QCommonStyle): diff --git a/qutebrowser/mainwindow/windowundo.py b/qutebrowser/mainwindow/windowundo.py index 34e1097c2..4335ad18d 100644 --- a/qutebrowser/mainwindow/windowundo.py +++ b/qutebrowser/mainwindow/windowundo.py @@ -20,10 +20,10 @@ """Code for :undo --window.""" import collections -from typing import MutableSequence, cast +from typing import Any, MutableSequence, cast -import attr -from PyQt5.QtCore import QObject +import dataclasses +from PyQt5.QtCore import QObject, QByteArray from qutebrowser.config import config from qutebrowser.mainwindow import mainwindow @@ -33,13 +33,13 @@ from qutebrowser.misc import objects instance = cast('WindowUndoManager', None) -@attr.s +@dataclasses.dataclass class _WindowUndoEntry: """Information needed for :undo -w.""" - geometry = attr.ib() - tab_stack = attr.ib() + geometry: QByteArray + tab_stack: Any # FIXME class WindowUndoManager(QObject): diff --git a/qutebrowser/misc/backendproblem.py b/qutebrowser/misc/backendproblem.py index fc8afe603..9f28fcef3 100644 --- a/qutebrowser/misc/backendproblem.py +++ b/qutebrowser/misc/backendproblem.py @@ -26,9 +26,9 @@ import html import enum import shutil import argparse -from typing import Any, List, Sequence, Tuple +from typing import Any, List, Sequence, Tuple, Optional -import attr +import dataclasses from PyQt5.QtCore import Qt from PyQt5.QtWidgets import (QDialog, QPushButton, QHBoxLayout, QVBoxLayout, QLabel, QMessageBox, QWidget) @@ -50,15 +50,15 @@ class _Result(enum.IntEnum): restart_webengine = QDialog.Accepted + 4 -@attr.s +@dataclasses.dataclass class _Button: """A button passed to BackendProblemDialog.""" - text: str = attr.ib() - setting: str = attr.ib() - value: Any = attr.ib() - default: bool = attr.ib(default=False) + text: str + setting: str + value: Any + default: bool = False def _other_backend(backend: usertypes.Backend) -> Tuple[usertypes.Backend, str]: @@ -150,15 +150,15 @@ class _Dialog(QDialog): self.done(_Result.restart) -@attr.s +@dataclasses.dataclass class _BackendImports: """Whether backend modules could be imported.""" - webkit_available: bool = attr.ib(default=None) - webengine_available: bool = attr.ib(default=None) - webkit_error: str = attr.ib(default=None) - webengine_error: str = attr.ib(default=None) + webkit_available: Optional[bool] = None + webengine_available: Optional[bool] = None + webkit_error: Optional[str] = None + webengine_error: Optional[str] = None class _BackendProblemChecker: diff --git a/qutebrowser/misc/crashsignal.py b/qutebrowser/misc/crashsignal.py index 1eaa608ba..47fb4c21b 100644 --- a/qutebrowser/misc/crashsignal.py +++ b/qutebrowser/misc/crashsignal.py @@ -29,9 +29,9 @@ import argparse import functools import threading import faulthandler -from typing import TYPE_CHECKING, Optional, MutableMapping, cast +from typing import TYPE_CHECKING, Optional, MutableMapping, cast, List +import dataclasses -import attr from PyQt5.QtCore import (pyqtSlot, qInstallMessageHandler, QObject, QSocketNotifier, QTimer, QUrl) from PyQt5.QtWidgets import QApplication @@ -44,14 +44,14 @@ if TYPE_CHECKING: from qutebrowser.misc import quitter -@attr.s +@dataclasses.dataclass class ExceptionInfo: """Information stored when there was an exception.""" - pages = attr.ib() - cmd_history = attr.ib() - objects = attr.ib() + pages: List[List[str]] + cmd_history: List[str] + objects: str crash_handler = cast('CrashHandler', None) diff --git a/qutebrowser/misc/throttle.py b/qutebrowser/misc/throttle.py index 3540d8824..777177ec8 100644 --- a/qutebrowser/misc/throttle.py +++ b/qutebrowser/misc/throttle.py @@ -22,17 +22,17 @@ import time from typing import Any, Callable, Mapping, Optional, Sequence -import attr +import dataclasses from PyQt5.QtCore import QObject from qutebrowser.utils import usertypes -@attr.s +@dataclasses.dataclass class _CallArgs: - args: Sequence[Any] = attr.ib() - kwargs: Mapping[str, Any] = attr.ib() + args: Sequence[Any] + kwargs: Mapping[str, Any] class Throttle(QObject): diff --git a/qutebrowser/utils/usertypes.py b/qutebrowser/utils/usertypes.py index 893dae877..d180a6699 100644 --- a/qutebrowser/utils/usertypes.py +++ b/qutebrowser/utils/usertypes.py @@ -23,7 +23,7 @@ import operator import enum from typing import Any, Optional, Sequence, TypeVar, Union -import attr +import dataclasses from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QTimer from PyQt5.QtCore import QUrl @@ -496,7 +496,7 @@ class AbstractCertificateErrorWrapper: raise NotImplementedError -@attr.s +@dataclasses.dataclass class NavigationRequest: """A request to navigate to the given URL.""" @@ -526,7 +526,7 @@ class NavigationRequest: #: None of the above. other = 8 - url: QUrl = attr.ib() - navigation_type: Type = attr.ib() - is_main_frame: bool = attr.ib() - accepted: bool = attr.ib(default=True) + url: QUrl + navigation_type: Type + is_main_frame: bool + accepted: bool = True diff --git a/qutebrowser/utils/version.py b/qutebrowser/utils/version.py index 3640aef10..10b73f167 100644 --- a/qutebrowser/utils/version.py +++ b/qutebrowser/utils/version.py @@ -33,7 +33,7 @@ import getpass import functools from typing import Mapping, Optional, Sequence, Tuple, cast -import attr +import dataclasses from PyQt5.QtCore import PYQT_VERSION_STR, QLibraryInfo from PyQt5.QtNetwork import QSslSocket from PyQt5.QtGui import (QOpenGLContext, QOpenGLVersionProfile, @@ -76,15 +76,15 @@ _LOGO = r''' ''' -@attr.s +@dataclasses.dataclass class DistributionInfo: """Information about the running distribution.""" - id: Optional[str] = attr.ib() - parsed: 'Distribution' = attr.ib() - version: Optional[utils.VersionNumber] = attr.ib() - pretty: str = attr.ib() + id: Optional[str] + parsed: 'Distribution' + version: Optional[utils.VersionNumber] + pretty: str pastebin_url = None @@ -623,27 +623,27 @@ def version_info() -> str: return '\n'.join(lines) -@attr.s +@dataclasses.dataclass class OpenGLInfo: """Information about the OpenGL setup in use.""" # If we're using OpenGL ES. If so, no further information is available. - gles: bool = attr.ib(False) + gles: bool = False # The name of the vendor. Examples: # - nouveau # - "Intel Open Source Technology Center", "Intel", "Intel Inc." - vendor: Optional[str] = attr.ib(None) + vendor: Optional[str] = None # The OpenGL version as a string. See tests for examples. - version_str: Optional[str] = attr.ib(None) + version_str: Optional[str] = None # The parsed version as a (major, minor) tuple of ints - version: Optional[Tuple[int, ...]] = attr.ib(None) + version: Optional[Tuple[int, ...]] = None # The vendor specific information following the version number - vendor_specific: Optional[str] = attr.ib(None) + vendor_specific: Optional[str] = None def __str__(self) -> str: if self.gles: |