Improve __repr__ methods.

This commit is contained in:
Florian Bruhin 2014-09-26 15:48:24 +02:00
parent 1960cfe114
commit 36fd2e5c7f
39 changed files with 115 additions and 94 deletions

View File

@ -150,7 +150,7 @@ class Application(QApplication):
self._crashdlg.raise_()
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)
return utils.get_repr(self)
def _init_config(self):
"""Inizialize and read the config."""

View File

@ -39,6 +39,6 @@ class DiskCache(QNetworkDiskCache):
self.setMaximumCacheSize(config.get('storage', 'cache-size'))
def __repr__(self):
return '<{} size={}, maxsize={}, path="{}">'.format(
self.__class__.__name__, self.cacheSize(), self.maximumCacheSize(),
self.cacheDirectory())
return utils.get_repr(self, size=self.cacheSize(),
maxsize=self.maximumCacheSize(),
path=self.cacheDirectory())

View File

@ -38,7 +38,7 @@ from qutebrowser.commands import userscripts, cmdexc, cmdutils
from qutebrowser.config import config
from qutebrowser.browser import quickmarks, webelem
from qutebrowser.utils import (message, editor, usertypes, log, qtutils,
urlutils, objreg)
urlutils, objreg, utils)
class CommandDispatcher:
@ -59,7 +59,7 @@ class CommandDispatcher:
self._editor = None
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)
return utils.get_repr(self)
def _count(self):
"""Convenience method to get the widget count."""

View File

@ -41,8 +41,7 @@ class CookieJar(QNetworkCookieJar):
self.setAllCookies(cookies)
def __repr__(self):
return '<{} count={}>'.format(
self.__class__.__name__, len(self.allCookies()))
return utils.get_repr(self, count=len(self.allCookies()))
def purge_old_cookies(self):
"""Purge expired cookies from the cookie jar."""

View File

@ -108,7 +108,7 @@ class DownloadItem(QObject):
self.timer.start()
def __repr__(self):
return '<{} "{}">'.format(self.__class__.__name__, self.basename)
return utils.get_repr(self, basename=self.basename)
def __str__(self):
"""Get the download as a string.
@ -349,7 +349,7 @@ class DownloadManager(QObject):
self.questions = []
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)
return utils.get_repr(self, downloads=len(self.downloads))
@pyqtSlot('QUrl', 'QWebPage')
def get(self, url, page):

View File

@ -117,9 +117,10 @@ class WebElementWrapper(collections.abc.MutableMapping):
def __repr__(self):
try:
return "<WebElementWrapper '{}'>".format(self.debug_text())
html = self.debug_text()
except IsNullError:
return "<WebElementWrapper null>"
html = None
return utils.get_repr(self, html=html)
def __getitem__(self, key):
self._check_vanished()

View File

@ -62,7 +62,7 @@ class SearchRunner(QObject):
self._flags = 0
def __repr__(self):
return '<{} text={}>'.format(self.__class__.__name__, self._text)
return utils.get_repr(self, text=self._text, flags=self._flags)
def _search(self, text, rev=False):
"""Search for a text on the current page.

View File

@ -35,7 +35,7 @@ from PyQt5.QtCore import pyqtSignal, QObject
from qutebrowser.utils import log
from qutebrowser.config import configdata, iniparsers, configtypes, textwrapper
from qutebrowser.commands import cmdexc, cmdutils
from qutebrowser.utils import message, objreg
from qutebrowser.utils import message, objreg, utils
from qutebrowser.utils.usertypes import Completion
@ -129,7 +129,7 @@ class ConfigManager(QObject):
return self._proxies[key]
def __repr__(self):
return '<{} {}>'.format(self.__class__.__name__, self._fname)
return utils.get_repr(self, fname=self._fname)
def __str__(self):
"""Get the whole config as a string."""
@ -458,7 +458,7 @@ class SectionProxy(collections.abc.MutableMapping):
self.name = name
def __repr__(self):
return '<{} {}>'.format(self.__class__.__name__, self.name)
return utils.get_repr(self, name=self.name)
def __getitem__(self, key):
if not self.conf.has_option(self.name, key):

View File

@ -23,7 +23,7 @@ import os
import os.path
import configparser
from qutebrowser.utils import log
from qutebrowser.utils import log, utils
class ReadConfigParser(configparser.ConfigParser):
@ -54,8 +54,8 @@ class ReadConfigParser(configparser.ConfigParser):
self.read(self._configfile, encoding='utf-8')
def __repr__(self):
return '{}("{}", "{}")'.format(
self.__class__.__name__, self._configdir, self._fname)
return utils.get_repr(self, constructor=True,
configdir=self._configdir, fname=self._fname)
class ReadWriteConfigParser(ReadConfigParser):

View File

@ -26,7 +26,7 @@ from PyQt5.QtCore import pyqtSignal, QObject
from qutebrowser.config import configdata, textwrapper
from qutebrowser.commands import cmdutils, cmdexc
from qutebrowser.utils import log
from qutebrowser.utils import log, utils
class KeyConfigError(Exception):
@ -99,8 +99,8 @@ class KeyConfigParser(QObject):
return '\n'.join(lines) + '\n'
def __repr__(self):
return '{}("{}", "{}")'.format(
self.__class__.__name__, self._configdir, self._fname)
return utils.get_repr(self, constructor=True,
configdir=self._configdir, fname=self._fname)
def _str_section_desc(self, sectname):
"""Get the section description string for sectname."""

View File

@ -24,7 +24,7 @@ import os.path
from PyQt5.QtCore import pyqtSlot
from qutebrowser.utils import log
from qutebrowser.utils import log, utils
class LineConfigParser:
@ -60,9 +60,9 @@ class LineConfigParser:
self.read(self._configfile)
def __repr__(self):
return '{}("{}", "{}", limit={}, binary={})'.format(
self.__class__.__name__, self._configdir, self._fname, self._limit,
self._binary)
return utils.get_repr(self, constructor=True,
configdir=self._configdir, fname=self._fname,
limit=self._limit, binary=self._binary)
def __iter__(self):
"""Iterate over the set data."""

View File

@ -88,9 +88,8 @@ class BaseKeyParser(QObject):
self.special_bindings = {}
def __repr__(self):
return '<{} supports_count={}, supports_chains={}>'.format(
self.__class__.__name__, self._supports_count,
self._supports_chains)
return utils.get_repr(self, supports_count=self._supports_count,
supports_chains=self._supports_chains)
def _debug_log(self, message):
"""Log a message to the debug log if logging is active.

View File

@ -20,7 +20,7 @@
"""Advanced keyparsers."""
from qutebrowser.keyinput.basekeyparser import BaseKeyParser
from qutebrowser.utils import message
from qutebrowser.utils import message, utils
from qutebrowser.commands import runners, cmdexc
@ -70,5 +70,5 @@ class PassthroughKeyParser(CommandKeyParser):
self._mode = mode
def __repr__(self):
return '<{} mode={}, warn={})'.format(
self.__class__.__name__, self._mode, self._warn_on_keychains)
return utils.get_repr(self, mode=self._mode,
warn=self._warn_on_keychains)

View File

@ -29,7 +29,7 @@ from PyQt5.QtWidgets import QApplication
from qutebrowser.config import config
from qutebrowser.commands import cmdexc, cmdutils
from qutebrowser.utils import usertypes, log, objreg
from qutebrowser.utils import usertypes, log, objreg, utils
class ModeLockedError(Exception):
@ -107,7 +107,8 @@ class ModeManager(QObject):
'forward-unbound-keys')
def __repr__(self):
return '<{} mode={}>'.format(self.__class__.__name__, self.mode())
return utils.get_repr(self, mode=self.mode(), locked=self.locked,
passthrough=self.passthrough)
def mode(self):
"""Get the current mode.."""

View File

@ -28,7 +28,7 @@ from PyQt5.QtCore import pyqtSlot, Qt
from qutebrowser.utils import message
from qutebrowser.config import config
from qutebrowser.keyinput import keyparser
from qutebrowser.utils import usertypes, log, objreg
from qutebrowser.utils import usertypes, log, objreg, utils
STARTCHARS = ":/?"
@ -44,7 +44,7 @@ class NormalKeyParser(keyparser.CommandKeyParser):
self.read_config('normal')
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)
return utils.get_repr(self)
def _handle_single_key(self, e):
"""Override _handle_single_key to abort if the key is a startchar.
@ -73,7 +73,7 @@ class PromptKeyParser(keyparser.CommandKeyParser):
self.read_config('prompt')
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)
return utils.get_repr(self)
class HintKeyParser(keyparser.CommandKeyParser):

View File

@ -23,7 +23,7 @@ from PyQt5.QtCore import (pyqtSlot, Qt, QVariant, QAbstractListModel,
QModelIndex)
from qutebrowser.config import config
from qutebrowser.utils import usertypes, qtutils, objreg
from qutebrowser.utils import usertypes, qtutils, objreg, utils
Role = usertypes.enum('Role', 'item', start=Qt.UserRole, is_int=True)
@ -49,7 +49,7 @@ class DownloadModel(QAbstractListModel):
download_manager.data_changed.connect(self.on_data_changed)
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)
return utils.get_repr(self, count=self.rowCount())
@pyqtSlot(int)
def on_data_changed(self, idx):

View File

@ -27,7 +27,7 @@ from unittest import mock
from qutebrowser.config import configtypes
from qutebrowser.test import stubs
from qutebrowser.utils import debug
from qutebrowser.utils import debug, utils
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QColor, QFont
@ -41,9 +41,9 @@ class Font(QFont):
def __repr__(self):
weight = debug.qenum_key(QFont, self.weight(), add_base=True,
klass=QFont.Weight)
return '<Font family={}, pt={}, px={}, weight={}, style={}>'.format(
self.family(), self.pointSize(), self.pixelSize(), weight,
self.style())
return utils.get_repr(self, family=self.family(), pt=self.pointSize(),
px=self.pixelSize(), weight=weight,
style=self.style())
@classmethod
def fromdesc(cls, desc):
@ -65,9 +65,9 @@ class NetworkProxy(QNetworkProxy):
"""A QNetworkProxy with a nicer repr()."""
def __repr__(self):
return 'QNetworkProxy({}, "{}", {}, "{}", "{}")'.format(
self.type(), self.hostName(), self.port(), self.user(),
self.password())
return utils.get_repr(self, type=self.type(), hostName=self.hostName(),
port=self.port(), user=self.user(),
password=self.password())
class ValidValuesTest(unittest.TestCase):

View File

@ -39,8 +39,9 @@ class Color(QColor):
"""A QColor with a nicer repr()."""
def __repr__(self):
return 'Color({}, {}, {}, {})'.format(
self.red(), self.green(), self.blue(), self.alpha())
return utils.get_repr(self, constructor=True, red=self.red(),
green=self.green(), blue=self.blue(),
alpha=self.alpha())
class ElidingTests(unittest.TestCase):

View File

@ -49,11 +49,6 @@ class InitTests(unittest.TestCase):
nl = usertypes.NeighborList([1, 2, 3])
self.assertEqual(len(nl), 3)
def test_repr(self):
"""Test repr() on NeighborList."""
nl = usertypes.NeighborList([1, 2, 3])
self.assertEqual(repr(nl), 'NeighborList([1, 2, 3])')
def test_contains(self):
"""Test 'in' on NeighborList."""
nl = usertypes.NeighborList([1, 2, 3])

View File

@ -23,7 +23,7 @@ from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject
from qutebrowser.config import config, configdata
from qutebrowser.commands import cmdutils
from qutebrowser.utils import usertypes, log, objreg
from qutebrowser.utils import usertypes, log, objreg, utils
from qutebrowser.models import completion as models
from qutebrowser.models.completionfilter import CompletionFilterModel as CFM
@ -59,7 +59,7 @@ class Completer(QObject):
self._init_setting_completions()
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)
return utils.get_repr(self)
def _model(self):
"""Convienience method to get the current completion model."""

View File

@ -21,7 +21,7 @@
from PyQt5.QtCore import pyqtSignal, QObject, QTimer
from qutebrowser.utils import usertypes, log, objreg
from qutebrowser.utils import usertypes, log, objreg, utils
def error(message, immediately=False):
@ -152,7 +152,7 @@ class MessageBridge(QObject):
s_question = pyqtSignal(usertypes.Question, bool)
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)
return utils.get_repr(self)
def _emit_later(self, signal, *args):
"""Emit a message later when the mainloop is not busy anymore.

View File

@ -23,6 +23,7 @@ from PyQt5.QtWidgets import QApplication, QLineEdit
from qutebrowser.commands import cmdutils
from qutebrowser.utils import usertypes as typ
from qutebrowser.utils import utils
class ReadlineBridge:
@ -37,7 +38,7 @@ class ReadlineBridge:
self._deleted = {}
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)
return utils.get_repr(self)
def _widget(self):
"""Get the currently active QLineEdit."""

View File

@ -26,7 +26,7 @@ import re
import pypeg2 as peg
from qutebrowser.utils import log
from qutebrowser.utils import log, utils
class UniqueNamespace(peg.Namespace):
@ -279,8 +279,8 @@ class ContentDisposition:
return self.disposition.lower() == 'inline'
def __repr__(self):
return 'ContentDisposition(%r, %r)' % (
self.disposition, self.assocs)
return utils.get_repr(self, constructor=True,
disposition=self.disposition, assocs=self.assocs)
def normalize_ws(text):

View File

@ -30,7 +30,7 @@ import enum as pyenum
from PyQt5.QtCore import pyqtSignal, QObject, QTimer
from qutebrowser.utils import log, qtutils
from qutebrowser.utils import log, qtutils, utils
_UNSET = object()
@ -103,7 +103,8 @@ class NeighborList(collections.abc.Sequence):
return len(self._items)
def __repr__(self):
return '{}({})'.format(self.__class__.__name__, self._items)
return utils.get_repr(self, items=self._items, mode=self._mode,
idx=self._idx, fuzzyval=self.fuzzyval)
def _snap_in(self, offset):
"""Set the current item to the closest item to self.fuzzyval.
@ -296,7 +297,8 @@ class Question(QObject):
self.is_aborted = False
def __repr__(self):
return '<{} "{}">'.format(self.__class__.__name__, self.text)
return utils.get_repr(self, text=self.text, mode=self._mode,
default=self.default)
@property
def mode(self):
@ -359,7 +361,7 @@ class Timer(QTimer):
self._name = name
def __repr__(self):
return '<{} {}>'.format(self.__class__.__name__, self._name)
return utils.get_repr(self, name=self._name)
def setInterval(self, msec):
"""Extend setInterval to check for overflows."""

View File

@ -582,3 +582,25 @@ def is_enum(obj):
return issubclass(obj, enum.Enum)
except TypeError:
return False
def get_repr(obj, constructor=False, **attrs):
"""Get a suitable __repr__ string for an object.
Args:
obj: The object to get a repr for.
constructor: If True, show the Foo(one=1, two=2) form instead of
<Foo one=1 two=2>.
attrs: The attributes to add.
"""
cls = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
parts = []
for name, val in attrs.items():
parts.append('{}={!r}'.format(name, val))
if constructor:
return '{}({})'.format(cls, ', '.join(parts))
else:
if parts:
return '<{} {}>'.format(cls, ' '.join(parts))
else:
return '<{}>'.format(cls)

View File

@ -29,7 +29,7 @@ from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QItemSelectionModel
from qutebrowser.commands import cmdutils
from qutebrowser.config import config, style
from qutebrowser.widgets import completiondelegate
from qutebrowser.utils import completer, usertypes, qtutils, objreg
from qutebrowser.utils import completer, usertypes, qtutils, objreg, utils
class CompletionView(QTreeView):
@ -116,7 +116,7 @@ class CompletionView(QTreeView):
# FIXME set elidemode
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)
return utils.get_repr(self)
def _resize_columns(self):
"""Resize the completion columns based on COLUMN_WIDTHS."""

View File

@ -162,7 +162,7 @@ class ConsoleTextEdit(QTextEdit):
self.setFocusPolicy(Qt.NoFocus)
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)
return utils.get_repr(self)
def on_config_changed(self, section, option):
"""Update font when config changed."""
@ -193,8 +193,7 @@ class ConsoleWidget(QWidget):
self._lineedit.setFocus()
def __repr__(self):
return '<{}, visible={}>'.format(
self.__class__.__name__, self.isVisible())
return utils.get_repr(self, visible=self.isVisible())
@pyqtSlot(str, str)
def on_config_changed(self, section, option):

View File

@ -78,7 +78,7 @@ class _CrashDialog(QDialog):
self._init_buttons()
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)
return utils.get_repr(self)
def _init_text(self):
"""Initialize the main text to be displayed on an exception.

View File

@ -24,7 +24,7 @@ from PyQt5.QtWidgets import QListView, QSizePolicy, QMenu
from qutebrowser.models import downloadmodel
from qutebrowser.config import style
from qutebrowser.utils import qtutils
from qutebrowser.utils import qtutils, utils
class DownloadView(QListView):
@ -64,8 +64,7 @@ class DownloadView(QListView):
self.customContextMenuRequested.connect(self.show_context_menu)
def __repr__(self):
return '<{} with {} downloads>'.format(self.__class__.__name__,
self.model().rowCount())
return utils.get_repr(self, count=self.model().rowCount())
@pyqtSlot('QPoint')
def show_context_menu(self, point):

View File

@ -27,7 +27,7 @@ from PyQt5.QtWidgets import QWidget, QVBoxLayout
from qutebrowser.commands import cmdutils
from qutebrowser.config import config
from qutebrowser.utils import message, log, usertypes, qtutils, objreg
from qutebrowser.utils import message, log, usertypes, qtutils, objreg, utils
from qutebrowser.widgets import tabbedbrowser, completion, downloads
from qutebrowser.widgets.statusbar import bar
@ -100,7 +100,7 @@ class MainWindow(QWidget):
#QtCore.QMetaObject.connectSlotsByName(MainWindow)
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)
return utils.get_repr(self)
def _connect_resize_completion(self):
"""Connect the resize_completion signal and resize it once."""

View File

@ -24,6 +24,7 @@ from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtGui import QValidator
from qutebrowser.models import cmdhistory
from qutebrowser.utils import utils
class MinimalLineEditMixin:
@ -41,7 +42,7 @@ class MinimalLineEditMixin:
self.setAttribute(Qt.WA_MacShowFocusRect, False)
def __repr__(self):
return '<{} "{}">'.format(self.__class__.__name__, self.text())
return utils.get_repr(self, text=self.text())
class CommandLineEdit(QLineEdit):
@ -94,7 +95,7 @@ class CommandLineEdit(QLineEdit):
self.setSelection(self._promptlen, oldpos - self._promptlen)
def __repr__(self):
return '<{} "{}">'.format(self.__class__.__name__, self.text())
return utils.get_repr(self, text=self.text())
class _CommandValidator(QValidator):

View File

@ -26,7 +26,7 @@ from PyQt5.QtCore import pyqtSignal, pyqtSlot, pyqtProperty, Qt
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QStackedLayout, QSizePolicy
from qutebrowser.config import config, style
from qutebrowser.utils import usertypes, log, objreg
from qutebrowser.utils import usertypes, log, objreg, utils
from qutebrowser.widgets.statusbar import (command, progress, keystring,
percentage, url, prompt)
from qutebrowser.widgets.statusbar import text as textwidget
@ -170,7 +170,7 @@ class StatusBar(QWidget):
self._hbox.addWidget(self.prog)
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)
return utils.get_repr(self)
@pyqtProperty(bool)
def error(self):

View File

@ -24,6 +24,7 @@ from PyQt5.QtWidgets import QProgressBar, QSizePolicy
from qutebrowser.widgets import webview
from qutebrowser.config import style
from qutebrowser.utils import utils
class Progress(QProgressBar):
@ -52,7 +53,7 @@ class Progress(QProgressBar):
self.hide()
def __repr__(self):
return '<{} {}%>'.format(self.__class__.__name__, self.value())
return utils.get_repr(self, value=self.value())
@pyqtSlot()
def on_load_started(self):

View File

@ -24,7 +24,7 @@ from PyQt5.QtWidgets import QHBoxLayout, QWidget, QLineEdit
from qutebrowser.widgets import misc
from qutebrowser.widgets.statusbar import textbase, prompter
from qutebrowser.utils import objreg
from qutebrowser.utils import objreg, utils
class PromptLineEdit(misc.MinimalLineEditMixin, QLineEdit):
@ -70,4 +70,4 @@ class Prompt(QWidget):
objreg.register('prompter', prompter_obj)
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)
return utils.get_repr(self)

View File

@ -26,7 +26,7 @@ from PyQt5.QtWidgets import QLineEdit
from qutebrowser.keyinput import modeman
from qutebrowser.commands import cmdutils
from qutebrowser.utils import usertypes, log, qtutils, objreg
from qutebrowser.utils import usertypes, log, qtutils, objreg, utils
PromptContext = collections.namedtuple('PromptContext',
@ -69,7 +69,9 @@ class Prompter:
self._busy = False
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)
return utils.get_repr(self, loops=len(self._loops),
question=self._question, queue=len(self._queue),
busy=self._busy)
def _pop_later(self):
"""Helper to call self._pop as soon as everything else is done."""

View File

@ -23,7 +23,7 @@ from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QLabel, QSizePolicy
from PyQt5.QtGui import QPainter
from qutebrowser.utils import qtutils
from qutebrowser.utils import qtutils, utils
class TextBase(QLabel):
@ -47,7 +47,7 @@ class TextBase(QLabel):
self._elided_text = ''
def __repr__(self):
return '<{} "{}">'.format(self.__class__.__name__, self.text())
return utils.get_repr(self, text=self.text())
def _update_elided_text(self, width):
"""Update the elided text when necessary.

View File

@ -112,8 +112,7 @@ class TabbedBrowser(tabwidget.TabWidget):
self.setIconSize(QSize(12, 12))
def __repr__(self):
return '<{} with {} tabs>'.format(self.__class__.__name__,
self.count())
return utils.get_repr(self, count=self.count())
def widgets(self):
"""Get a list of open tab widgets.

View File

@ -31,7 +31,7 @@ from PyQt5.QtWidgets import (QTabWidget, QTabBar, QSizePolicy, QCommonStyle,
QStyle, QStylePainter, QStyleOptionTab)
from PyQt5.QtGui import QIcon, QPalette, QColor
from qutebrowser.utils import qtutils, objreg
from qutebrowser.utils import qtutils, objreg, utils
from qutebrowser.config import config
@ -110,8 +110,7 @@ class TabBar(QTabBar):
QTimer.singleShot(0, self._autohide)
def __repr__(self):
return '<{} with {} tabs>'.format(self.__class__.__name__,
self.count())
return utils.get_repr(self, count=self.count())
def _autohide(self):
"""Auto-hide the tabbar if needed."""

View File

@ -112,8 +112,8 @@ class WebView(QWebView):
self.viewing_source = False
def __repr__(self):
url = self.url().toDisplayString()
return "WebView(url='{}')".format(utils.elide(url, 50))
url = utils.elide(self.url().toDisplayString(), 50)
return utils.get_repr(self, url=url)
def _set_load_status(self, val):
"""Setter for load_status.