Clean up imports

This commit is contained in:
Florian Bruhin 2014-08-26 19:10:14 +02:00
parent 45608ee9f8
commit d625cde28c
99 changed files with 1467 additions and 1458 deletions

View File

@ -289,7 +289,7 @@ or
[source,python]
----
import qutebrowser.utils.log as log
from qutebrowser.utils import log
...
log.foo.debug("Hello World")
----

View File

@ -20,9 +20,10 @@
"""Entry point for qutebrowser. Simply execute qutebrowser."""
import qutebrowser.qutebrowser
import sys
import qutebrowser.qutebrowser
if __name__ == '__main__':
sys.exit(qutebrowser.qutebrowser.main())

View File

@ -26,46 +26,28 @@ import faulthandler
import configparser
import signal
import warnings
from bdb import BdbQuit
from base64 import b64encode
from functools import partial
import bdb
import base64
import functools
from PyQt5.QtWidgets import QApplication, QDialog, QMessageBox
from PyQt5.QtCore import (pyqtSlot, QTimer, QEventLoop, Qt, QStandardPaths,
qInstallMessageHandler, QObject, QUrl)
import qutebrowser
import qutebrowser.commands.utils as cmdutils
import qutebrowser.config.style as style
import qutebrowser.config.config as config
import qutebrowser.network.qutescheme as qutescheme
import qutebrowser.config.websettings as websettings
import qutebrowser.network.proxy as proxy
import qutebrowser.browser.quickmarks as quickmarks
import qutebrowser.utils.log as log
import qutebrowser.utils.version as version
import qutebrowser.utils.url as urlutils
import qutebrowser.utils.message as message
import qutebrowser.commands.userscripts as userscripts
import qutebrowser.utils.utilcmds as utilcmds
from qutebrowser.config.config import ConfigManager
from qutebrowser.keyinput.modeman import ModeManager
from qutebrowser.widgets.mainwindow import MainWindow
from qutebrowser.widgets.console import ConsoleWidget
from qutebrowser.widgets.crash import (ExceptionCrashDialog, FatalCrashDialog,
ReportDialog)
from qutebrowser.keyinput.modeparsers import (NormalKeyParser, HintKeyParser,
PromptKeyParser)
from qutebrowser.keyinput.keyparser import PassthroughKeyParser
from qutebrowser.commands.runners import CommandRunner, SearchRunner
from qutebrowser.config.iniparsers import ReadWriteConfigParser
from qutebrowser.config.lineparser import LineConfigParser
from qutebrowser.browser.cookies import CookieJar
from qutebrowser.browser.downloads import DownloadManager
from qutebrowser.utils.misc import get_standard_dir, actute_warning
from qutebrowser.utils.qt import get_qt_args
from qutebrowser.utils.readline import ReadlineBridge
from qutebrowser.utils.usertypes import Timer, KeyMode
from qutebrowser.commands import userscripts, runners
from qutebrowser.commands import utils as cmdutils
from qutebrowser.config import (style, config, websettings, iniparsers,
lineparser, conftypes)
from qutebrowser.network import qutescheme, proxy
from qutebrowser.browser import quickmarks, cookies, downloads
from qutebrowser.widgets import mainwindow, console, crash
from qutebrowser.keyinput import modeparsers, keyparser, modeman
from qutebrowser.utils import log, version, message, utilcmds, readline
from qutebrowser.utils import url as urlutils
from qutebrowser.utils import misc as utils
from qutebrowser.utils import qt as qtutils
from qutebrowser.utils import usertypes as utypes
class Application(QApplication):
@ -104,9 +86,9 @@ class Application(QApplication):
# We don't enable this earlier because some imports trigger
# warnings (which are not our fault).
warnings.simplefilter('default')
qt_args = get_qt_args(args)
qt_args = qtutils.get_qt_args(args)
log.init.debug("Qt arguments: {}, based on {}".format(qt_args, args))
super().__init__(get_qt_args(args))
super().__init__(qt_args)
self._quit_status = {
'crash': True,
'tabs': False,
@ -129,7 +111,7 @@ class Application(QApplication):
self.args = args
log.init.debug("Starting init...")
self._init_misc()
actute_warning()
utils.actute_warning()
log.init.debug("Initializing config...")
self._init_config()
log.init.debug("Initializing crashlog...")
@ -147,25 +129,25 @@ class Application(QApplication):
log.init.debug("Initializing utility commands...")
utilcmds.init()
log.init.debug("Initializing cookies...")
self.cookiejar = CookieJar(self)
self.cookiejar = cookies.CookieJar(self)
log.init.debug("Initializing commands...")
self.commandrunner = CommandRunner()
self.commandrunner = runners.CommandRunner()
log.init.debug("Initializing search...")
self.searchrunner = SearchRunner(self)
self.searchrunner = runners.SearchRunner(self)
log.init.debug("Initializing downloads...")
self.downloadmanager = DownloadManager(self)
self.downloadmanager = downloads.DownloadManager(self)
log.init.debug("Initializing main window...")
self.mainwindow = MainWindow()
self.mainwindow = mainwindow.MainWindow()
self.modeman.mainwindow = self.mainwindow
log.init.debug("Initializing debug console...")
self.debugconsole = ConsoleWidget()
self.debugconsole = console.ConsoleWidget()
log.init.debug("Initializing eventfilter...")
self.installEventFilter(self.modeman)
self.setQuitOnLastWindowClosed(False)
log.init.debug("Connecting signals...")
self._connect_signals()
self.modeman.enter(KeyMode.normal, 'init')
self.modeman.enter(utypes.KeyMode.normal, 'init')
log.init.debug("Showing mainwindow...")
if not args.nowindow:
@ -183,14 +165,15 @@ class Application(QApplication):
def _init_config(self):
"""Inizialize and read the config."""
if self.args.confdir is None:
confdir = get_standard_dir(QStandardPaths.ConfigLocation)
confdir = utils.get_standard_dir(QStandardPaths.ConfigLocation)
elif self.args.confdir == '':
confdir = None
else:
confdir = self.args.confdir
try:
self.config = ConfigManager(confdir, 'qutebrowser.conf', self)
except (config.ValidationError,
self.config = config.ConfigManager(confdir, 'qutebrowser.conf',
self)
except (conftypes.ValidationError,
config.NoOptionError,
config.InterpolationSyntaxError,
configparser.InterpolationError,
@ -207,47 +190,49 @@ class Application(QApplication):
msgbox.exec_()
# We didn't really initialize much so far, so we just quit hard.
sys.exit(1)
self.stateconfig = ReadWriteConfigParser(confdir, 'state')
self.cmd_history = LineConfigParser(confdir, 'cmd_history',
('completion', 'history-length'))
self.stateconfig = iniparsers.ReadWriteConfigParser(confdir, 'state')
self.cmd_history = lineparser.LineConfigParser(
confdir, 'cmd_history', ('completion', 'history-length'))
def _init_modes(self):
"""Inizialize the mode manager and the keyparsers."""
self._keyparsers = {
KeyMode.normal:
NormalKeyParser(self),
KeyMode.hint:
HintKeyParser(self),
KeyMode.insert:
PassthroughKeyParser('keybind.insert', self),
KeyMode.passthrough:
PassthroughKeyParser('keybind.passthrough', self),
KeyMode.command:
PassthroughKeyParser('keybind.command', self),
KeyMode.prompt:
PassthroughKeyParser('keybind.prompt', self, warn=False),
KeyMode.yesno:
PromptKeyParser(self),
utypes.KeyMode.normal:
modeparsers.NormalKeyParser(self),
utypes.KeyMode.hint:
modeparsers.HintKeyParser(self),
utypes.KeyMode.insert:
keyparser.PassthroughKeyParser('keybind.insert', self),
utypes.KeyMode.passthrough:
keyparser.PassthroughKeyParser('keybind.passthrough', self),
utypes.KeyMode.command:
keyparser.PassthroughKeyParser('keybind.command', self),
utypes.KeyMode.prompt:
keyparser.PassthroughKeyParser('keybind.prompt', self,
warn=False),
utypes.KeyMode.yesno:
modeparsers.PromptKeyParser(self),
}
self.modeman = ModeManager(self)
self.modeman.register(KeyMode.normal,
self._keyparsers[KeyMode.normal].handle)
self.modeman.register(KeyMode.hint,
self._keyparsers[KeyMode.hint].handle)
self.modeman.register(KeyMode.insert,
self._keyparsers[KeyMode.insert].handle,
self.modeman = modeman.ModeManager(self)
self.modeman.register(utypes.KeyMode.normal,
self._keyparsers[utypes.KeyMode.normal].handle)
self.modeman.register(utypes.KeyMode.hint,
self._keyparsers[utypes.KeyMode.hint].handle)
self.modeman.register(utypes.KeyMode.insert,
self._keyparsers[utypes.KeyMode.insert].handle,
passthrough=True)
self.modeman.register(KeyMode.passthrough,
self._keyparsers[KeyMode.passthrough].handle,
self.modeman.register(
utypes.KeyMode.passthrough,
self._keyparsers[utypes.KeyMode.passthrough].handle,
passthrough=True)
self.modeman.register(utypes.KeyMode.command,
self._keyparsers[utypes.KeyMode.command].handle,
passthrough=True)
self.modeman.register(KeyMode.command,
self._keyparsers[KeyMode.command].handle,
self.modeman.register(utypes.KeyMode.prompt,
self._keyparsers[utypes.KeyMode.prompt].handle,
passthrough=True)
self.modeman.register(KeyMode.prompt,
self._keyparsers[KeyMode.prompt].handle,
passthrough=True)
self.modeman.register(KeyMode.yesno,
self._keyparsers[KeyMode.yesno].handle)
self.modeman.register(utypes.KeyMode.yesno,
self._keyparsers[utypes.KeyMode.yesno].handle)
def _init_misc(self):
"""Initialize misc things."""
@ -263,7 +248,7 @@ class Application(QApplication):
self.setApplicationName("qutebrowser")
self.setApplicationVersion(qutebrowser.__version__)
self.messagebridge = message.MessageBridge(self)
self.rl_bridge = ReadlineBridge()
self.rl_bridge = readline.ReadlineBridge()
def _handle_segfault(self):
"""Handle a segfault from a previous run."""
@ -272,8 +257,8 @@ class Application(QApplication):
# However this also means if the logfile is there for some weird
# reason, we'll *always* log to stderr, but that's still better than no
# dialogs at all.
logname = os.path.join(get_standard_dir(QStandardPaths.DataLocation),
'crash.log')
path = utils.get_standard_dir(QStandardPaths.DataLocation)
logname = os.path.join(path, 'crash.log')
# First check if an old logfile exists.
if os.path.exists(logname):
with open(logname, 'r', encoding='ascii') as f:
@ -287,7 +272,7 @@ class Application(QApplication):
log.init.warning("Could not remove crash log!")
else:
self._init_crashlogfile()
self._crashdlg = FatalCrashDialog(data)
self._crashdlg = crash.FatalCrashDialog(data)
self._crashdlg.show()
else:
# Crashlog exists but without data.
@ -307,8 +292,8 @@ class Application(QApplication):
def _init_crashlogfile(self):
"""Start a new logfile and redirect faulthandler to it."""
logname = os.path.join(get_standard_dir(QStandardPaths.DataLocation),
'crash.log')
path = utils.get_standard_dir(QStandardPaths.DataLocation)
logname = os.path.join(path, 'crash.log')
self._crashlogfile = open(logname, 'w', encoding='ascii')
faulthandler.enable(self._crashlogfile)
if (hasattr(faulthandler, 'register') and
@ -360,7 +345,7 @@ class Application(QApplication):
"""
signal.signal(signal.SIGINT, self.interrupt)
signal.signal(signal.SIGTERM, self.interrupt)
timer = Timer(self, 'python_hacks')
timer = utypes.Timer(self, 'python_hacks')
timer.start(500)
timer.timeout.connect(lambda: None)
self._timers.append(timer)
@ -392,15 +377,16 @@ class Application(QApplication):
cmd.got_search_rev.connect(self.searchrunner.search_rev)
cmd.returnPressed.connect(tabs.setFocus)
self.searchrunner.do_search.connect(tabs.search)
kp[KeyMode.normal].keystring_updated.connect(status.keystring.setText)
kp[utypes.KeyMode.normal].keystring_updated.connect(
status.keystring.setText)
tabs.got_cmd.connect(self.commandrunner.run_safely)
# hints
kp[KeyMode.hint].fire_hint.connect(tabs.fire_hint)
kp[KeyMode.hint].filter_hints.connect(tabs.filter_hints)
kp[KeyMode.hint].keystring_updated.connect(tabs.handle_hint_key)
kp[utypes.KeyMode.hint].fire_hint.connect(tabs.fire_hint)
kp[utypes.KeyMode.hint].filter_hints.connect(tabs.filter_hints)
kp[utypes.KeyMode.hint].keystring_updated.connect(tabs.handle_hint_key)
tabs.hint_strings_updated.connect(
kp[KeyMode.hint].on_hint_strings_updated)
kp[utypes.KeyMode.hint].on_hint_strings_updated)
# messages
self.messagebridge.s_error.connect(status.disp_error)
@ -413,8 +399,8 @@ class Application(QApplication):
# config
self.config.style_changed.connect(style.invalidate_caches)
for obj in (tabs, completion, self.mainwindow, self.cmd_history,
websettings, kp[KeyMode.normal], self.modeman, status,
status.txt):
websettings, kp[utypes.KeyMode.normal], self.modeman,
status, status.txt):
self.config.changed.connect(obj.on_config_changed)
# statusbar
@ -498,7 +484,8 @@ class Application(QApplication):
def _save_geometry(self):
"""Save the window geometry to the state config."""
geom = b64encode(bytes(self.mainwindow.saveGeometry())).decode('ASCII')
data = bytes(self.mainwindow.saveGeometry())
geom = base64.b64encode(data).decode('ASCII')
try:
self.stateconfig.add_section('geometry')
except configparser.DuplicateSectionError:
@ -530,7 +517,7 @@ class Application(QApplication):
"""
# pylint: disable=broad-except
if exctype is BdbQuit or not issubclass(exctype, Exception):
if exctype is bdb.BdbQuit or not issubclass(exctype, Exception):
# pdb exit, KeyboardInterrupt, ...
try:
self.shutdown()
@ -580,8 +567,8 @@ class Application(QApplication):
log.destroy.debug("Error while preventing shutdown: {}: {}".format(
e.__class__.__name__, e))
QApplication.closeAllWindows()
self._crashdlg = ExceptionCrashDialog(pages, history, exc, widgets,
objects)
self._crashdlg = crash.ExceptionCrashDialog(pages, history, exc,
widgets, objects)
ret = self._crashdlg.exec_()
if ret == QDialog.Accepted: # restore
self.restart(shutdown=False, pages=pages)
@ -655,7 +642,7 @@ class Application(QApplication):
history = self.mainwindow.status.cmd.history[-5:]
widgets = self.get_all_widgets()
objects = self.get_all_objects()
self._crashdlg = ReportDialog(pages, history, widgets, objects)
self._crashdlg = crash.ReportDialog(pages, history, widgets, objects)
self._crashdlg.show()
@cmdutils.register(instance='', debug=True, name='debug-console')
@ -674,7 +661,7 @@ class Application(QApplication):
signal.signal(signal.SIGINT, self.interrupt_forcefully)
signal.signal(signal.SIGTERM, self.interrupt_forcefully)
# If we call shutdown directly here, we get a segfault.
QTimer.singleShot(0, partial(self.shutdown, 128 + signum))
QTimer.singleShot(0, functools.partial(self.shutdown, 128 + signum))
def interrupt_forcefully(self, signum, _frame):
"""Interrupt forcefully on the second SIGINT/SIGTERM request.
@ -689,7 +676,7 @@ class Application(QApplication):
signal.signal(signal.SIGTERM, self.interrupt_really_forcefully)
# This *should* work without a QTimer, but because of the trouble in
# self.interrupt we're better safe than sorry.
QTimer.singleShot(0, partial(self.exit, 128 + signum))
QTimer.singleShot(0, functools.partial(self.exit, 128 + signum))
def interrupt_really_forcefully(self, signum, _frame):
"""Interrupt with even more force on the third SIGINT/SIGTERM request.
@ -722,7 +709,7 @@ class Application(QApplication):
# in the real main event loop, or we'll get a segfault.
log.destroy.debug("Deferring real shutdown because question was "
"active.")
QTimer.singleShot(0, partial(self._shutdown, status))
QTimer.singleShot(0, functools.partial(self._shutdown, status))
else:
# If we have no questions to shut down, we are already in the real
# event loop, so we can shut down immediately.
@ -773,7 +760,7 @@ class Application(QApplication):
log.destroy.debug("Deferring QApplication::exit...")
# We use a singleshot timer to exit here to minimize the likelyhood of
# segfaults.
QTimer.singleShot(0, partial(self.exit, status))
QTimer.singleShot(0, functools.partial(self.exit, status))
def exit(self, status):
"""Extend QApplication::exit to log the event."""

View File

@ -29,19 +29,14 @@ from PyQt5.QtGui import QClipboard
from PyQt5.QtPrintSupport import QPrintDialog, QPrintPreviewDialog
from PyQt5.QtWebKitWidgets import QWebInspector
import qutebrowser.commands.utils as cmdutils
import qutebrowser.config.config as config
import qutebrowser.browser.hints as hints
import qutebrowser.utils.message as message
import qutebrowser.utils.webelem as webelem
import qutebrowser.browser.quickmarks as quickmarks
import qutebrowser.utils.log as log
import qutebrowser.utils.url as urlutils
import qutebrowser.commands.userscripts as userscripts
from qutebrowser.utils.qt import check_overflow, check_print_compat
from qutebrowser.utils.editor import ExternalEditor
from qutebrowser.commands.exceptions import CommandError
from qutebrowser.utils.usertypes import KeyMode
from qutebrowser.commands import userscripts
from qutebrowser.commands import utils as cmdutils
from qutebrowser.commands import exceptions as cmdexc
from qutebrowser.config import config
from qutebrowser.browser import hints, quickmarks
from qutebrowser.utils import message, webelem, editor, usertypes, log
from qutebrowser.utils import qt as qtutils
from qutebrowser.utils import url as urlutils
class CommandDispatcher:
@ -82,7 +77,7 @@ class CommandDispatcher:
perc = int(count)
else:
perc = float(perc)
perc = check_overflow(perc, 'int', fatal=False)
perc = qtutils.check_overflow(perc, 'int', fatal=False)
frame = self._tabs.currentWidget().page().currentFrame()
m = frame.scrollBarMaximum(orientation)
if m == 0:
@ -94,7 +89,7 @@ class CommandDispatcher:
widget = self._tabs.currentWidget()
frame = widget.page().currentFrame()
if frame is None:
raise CommandError("No frame focused!")
raise cmdexc.CommandError("No frame focused!")
widget.hintmanager.follow_prevnext(frame, self._tabs.current_url(),
prev, newtab)
@ -130,10 +125,10 @@ class CommandDispatcher:
def _tab_focus_last(self):
"""Select the tab which was last focused."""
if self._tabs.last_focused is None:
raise CommandError("No last focused tab!")
raise cmdexc.CommandError("No last focused tab!")
idx = self._tabs.indexOf(self._tabs.last_focused)
if idx == -1:
raise CommandError("Last focused tab vanished!")
raise cmdexc.CommandError("Last focused tab vanished!")
self._tabs.setCurrentIndex(idx)
def _editor_cleanup(self, oshandle, filename):
@ -142,7 +137,7 @@ class CommandDispatcher:
try:
os.remove(filename)
except PermissionError:
raise CommandError("Failed to delete tempfile...")
raise cmdexc.CommandError("Failed to delete tempfile...")
@cmdutils.register(instance='mainwindow.tabs.cmd')
def tab_close(self, count=None):
@ -173,7 +168,7 @@ class CommandDispatcher:
try:
url = urlutils.fuzzy_url(urlstr)
except urlutils.FuzzyUrlError as e:
raise CommandError(e)
raise cmdexc.CommandError(e)
if tab is None:
if count is None:
# We want to open a URL in the current tab, but none exists
@ -214,9 +209,9 @@ class CommandDispatcher:
Args:
count: The tab index to print, or None.
"""
if not check_print_compat():
raise CommandError("Printing on Qt < 5.3.0 on Windows is broken, "
"please upgrade!")
if not qtutils.check_print_compat():
raise cmdexc.CommandError(
"Printing on Qt < 5.3.0 on Windows is broken, please upgrade!")
tab = self._tabs.cntwidget(count)
if tab is not None:
preview = QPrintPreviewDialog()
@ -231,9 +226,9 @@ class CommandDispatcher:
Args:
count: The tab index to print, or None.
"""
if not check_print_compat():
raise CommandError("Printing on Qt < 5.3.0 on Windows is broken, "
"please upgrade!")
if not qtutils.check_print_compat():
raise cmdexc.CommandError(
"Printing on Qt < 5.3.0 on Windows is broken, please upgrade!")
tab = self._tabs.cntwidget(count)
if tab is not None:
printdiag = QPrintDialog()
@ -303,15 +298,17 @@ class CommandDispatcher:
widget = self._tabs.currentWidget()
frame = widget.page().mainFrame()
if frame is None:
raise CommandError("No frame focused!")
raise cmdexc.CommandError("No frame focused!")
try:
group_enum = webelem.Group[group.replace('-', '_')]
except KeyError:
raise CommandError("Unknown hinting group {}!".format(group))
raise cmdexc.CommandError("Unknown hinting group {}!".format(
group))
try:
target_enum = hints.Target[target.replace('-', '_')]
except KeyError:
raise CommandError("Unknown hinting target {}!".format(target))
raise cmdexc.CommandError("Unknown hinting target {}!".format(
target))
widget.hintmanager.start(frame, self._tabs.current_url(), group_enum,
target_enum, *args)
@ -488,7 +485,7 @@ class CommandDispatcher:
try:
level = cmdutils.arg_or_count(zoom, count, default=100)
except ValueError as e:
raise CommandError(e)
raise cmdexc.CommandError(e)
tab = self._tabs.currentWidget()
tab.zoom_perc(level)
@ -506,7 +503,7 @@ class CommandDispatcher:
try:
url = urlutils.fuzzy_url(urlstr)
except urlutils.FuzzyUrlError as e:
raise CommandError(e)
raise cmdexc.CommandError(e)
self._tabs.tabopen(url, background=False, explicit=True)
@cmdutils.register(instance='mainwindow.tabs.cmd', split=False)
@ -515,7 +512,7 @@ class CommandDispatcher:
try:
url = urlutils.fuzzy_url(urlstr)
except urlutils.FuzzyUrlError as e:
raise CommandError(e)
raise cmdexc.CommandError(e)
self._tabs.tabopen(url, background=True, explicit=True)
@cmdutils.register(instance='mainwindow.tabs.cmd')
@ -524,7 +521,7 @@ class CommandDispatcher:
if self._tabs.url_stack:
self._tabs.tabopen(self._tabs.url_stack.pop())
else:
raise CommandError("Nothing to undo!")
raise cmdexc.CommandError("Nothing to undo!")
@cmdutils.register(instance='mainwindow.tabs.cmd')
def tab_prev(self, count=1):
@ -539,7 +536,7 @@ class CommandDispatcher:
elif config.get('tabs', 'wrap'):
self._tabs.setCurrentIndex(newidx % self._tabs.count())
else:
raise CommandError("First tab")
raise cmdexc.CommandError("First tab")
@cmdutils.register(instance='mainwindow.tabs.cmd')
def tab_next(self, count=1):
@ -554,7 +551,7 @@ class CommandDispatcher:
elif config.get('tabs', 'wrap'):
self._tabs.setCurrentIndex(newidx % self._tabs.count())
else:
raise CommandError("Last tab")
raise cmdexc.CommandError("Last tab")
@cmdutils.register(instance='mainwindow.tabs.cmd', nargs=(0, 1))
def paste(self, sel=False, tab=False):
@ -573,12 +570,12 @@ class CommandDispatcher:
target = "Clipboard"
text = clipboard.text(mode)
if not text:
raise CommandError("{} is empty.".format(target))
raise cmdexc.CommandError("{} is empty.".format(target))
log.misc.debug("{} contained: '{}'".format(target, text))
try:
url = urlutils.fuzzy_url(text)
except urlutils.FuzzyUrlError as e:
raise CommandError(e)
raise cmdexc.CommandError(e)
if tab:
self._tabs.tabopen(url, explicit=True)
else:
@ -610,12 +607,13 @@ class CommandDispatcher:
idx = cmdutils.arg_or_count(index, count, default=1,
countzero=self._tabs.count())
except ValueError as e:
raise CommandError(e)
raise cmdexc.CommandError(e)
cmdutils.check_overflow(idx + 1, 'int')
if 1 <= idx <= self._tabs.count():
self._tabs.setCurrentIndex(idx - 1)
else:
raise CommandError("There's no tab with index {}!".format(idx))
raise cmdexc.CommandError("There's no tab with index {}!".format(
idx))
@cmdutils.register(instance='mainwindow.tabs.cmd')
def tab_move(self, direction=None, count=None):
@ -632,11 +630,13 @@ class CommandDispatcher:
try:
new_idx = self._tab_move_relative(direction, count)
except ValueError:
raise CommandError("Count must be given for relative moving!")
raise cmdexc.CommandError("Count must be given for relative "
"moving!")
else:
raise CommandError("Invalid direction '{}'!".format(direction))
raise cmdexc.CommandError("Invalid direction '{}'!".format(
direction))
if not 0 <= new_idx < self._tabs.count():
raise CommandError("Can't move tab to position {}!".format(
raise cmdexc.CommandError("Can't move tab to position {}!".format(
new_idx))
tab = self._tabs.currentWidget()
cur_idx = self._tabs.currentIndex()
@ -697,7 +697,7 @@ class CommandDispatcher:
urlstr = quickmarks.get(name)
url = QUrl(urlstr)
if not url.isValid():
raise CommandError("Invalid URL {} ({})".format(
raise cmdexc.CommandError("Invalid URL {} ({})".format(
urlstr, url.errorString()))
self._tabs.currentWidget().openurl(url)
@ -719,8 +719,9 @@ class CommandDispatcher:
cur = self._tabs.currentWidget()
if cur.inspector is None:
if not config.get('general', 'developer-extras'):
raise CommandError("Please enable developer-extras before "
"using the webinspector!")
raise cmdexc.CommandError(
"Please enable developer-extras before using the "
"webinspector!")
cur.inspector = QWebInspector()
cur.inspector.setPage(cur.page())
cur.inspector.show()
@ -728,8 +729,9 @@ class CommandDispatcher:
cur.inspector.hide()
else:
if not config.get('general', 'developer-extras'):
raise CommandError("Please enable developer-extras before "
"using the webinspector!")
raise cmdexc.CommandError(
"Please enable developer-extras before using the "
"webinspector!")
else:
cur.inspector.show()
@ -739,7 +741,8 @@ class CommandDispatcher:
page = self._tabs.currentWidget().page()
self._tabs.download_get.emit(self._tabs.current_url(), page)
@cmdutils.register(instance='mainwindow.tabs.cmd', modes=[KeyMode.insert],
@cmdutils.register(instance='mainwindow.tabs.cmd',
modes=[usertypes.KeyMode.insert],
hide=True)
def open_editor(self):
"""Open an external editor with the currently selected form field.
@ -756,14 +759,14 @@ class CommandDispatcher:
frame = self._tabs.currentWidget().page().currentFrame()
elem = webelem.focus_elem(frame)
if elem.isNull():
raise CommandError("No element focused!")
raise cmdexc.CommandError("No element focused!")
if not webelem.is_editable(elem, strict=True):
raise CommandError("Focused element is not editable!")
raise cmdexc.CommandError("Focused element is not editable!")
if webelem.is_content_editable(elem):
text = elem.toPlainText()
else:
text = elem.evaluateJavaScript('this.value')
self._editor = ExternalEditor(self._tabs)
self._editor = editor.ExternalEditor(self._tabs)
self._editor.editing_finished.connect(
partial(self.on_editing_finished, elem))
self._editor.edit(text)
@ -778,7 +781,7 @@ class CommandDispatcher:
text: The new text to insert.
"""
if elem.isNull():
raise CommandError("Element vanished while editing!")
raise cmdexc.CommandError("Element vanished while editing!")
if webelem.is_content_editable(elem):
log.misc.debug("Filling element {} via setPlainText.".format(
webelem.debug_text(elem)))

View File

@ -22,9 +22,8 @@
from PyQt5.QtNetwork import QNetworkCookie, QNetworkCookieJar
from PyQt5.QtCore import QStandardPaths, QDateTime
import qutebrowser.config.config as config
from qutebrowser.config.lineparser import LineConfigParser
from qutebrowser.utils.misc import get_standard_dir
from qutebrowser.config import config, lineparser
from qutebrowser.utils import misc as utils
class CookieJar(QNetworkCookieJar):
@ -33,8 +32,8 @@ class CookieJar(QNetworkCookieJar):
def __init__(self, parent=None):
super().__init__(parent)
datadir = get_standard_dir(QStandardPaths.DataLocation)
self._linecp = LineConfigParser(datadir, 'cookies')
datadir = utils.get_standard_dir(QStandardPaths.DataLocation)
self._linecp = lineparser.LineConfigParser(datadir, 'cookies')
cookies = []
for line in self._linecp:
cookies += QNetworkCookie.parseCookies(line.encode('utf-8'))

View File

@ -21,21 +21,19 @@
import os
import os.path
from functools import partial
from collections import deque
import functools
import collections
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject, QTimer, QStandardPaths
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
import qutebrowser.config.config as config
import qutebrowser.utils.message as message
import qutebrowser.commands.utils as cmdutils
import qutebrowser.utils.misc as utils
from qutebrowser.utils.http import parse_content_disposition
from qutebrowser.config import config
from qutebrowser.commands import utils as cmdutils
from qutebrowser.commands import exceptions as cmdexc
from qutebrowser.utils import message, http, usertypes
from qutebrowser.utils import misc as utils
from qutebrowser.utils import qt as qtutils
from qutebrowser.utils.log import downloads as logger
from qutebrowser.utils.usertypes import PromptMode, Question, Timer
from qutebrowser.utils.qt import qt_ensure_valid
from qutebrowser.commands.exceptions import CommandError
class DownloadItem(QObject):
@ -92,7 +90,7 @@ class DownloadItem(QObject):
self.basename = '???'
samples = int(self.SPEED_AVG_WINDOW *
(1000 / self.SPEED_REFRESH_INTERVAL))
self.speed_avg = deque(maxlen=samples)
self.speed_avg = collections.deque(maxlen=samples)
self.fileobj = None
self.filename = None
self.is_cancelled = False
@ -111,7 +109,7 @@ class DownloadItem(QObject):
QTimer.singleShot(0, lambda: self.error.emit(reply.errorString()))
if reply.isFinished():
QTimer.singleShot(0, self.finished.emit)
self.timer = Timer(self, 'speed_refresh')
self.timer = usertypes.Timer(self, 'speed_refresh')
self.timer.timeout.connect(self.update_speed)
self.timer.setInterval(self.SPEED_REFRESH_INTERVAL)
self.timer.start()
@ -349,7 +347,7 @@ class DownloadManager(QObject):
url: The URL to get, as QUrl
page: The QWebPage to get the download from.
"""
qt_ensure_valid(url)
qtutils.qt_ensure_valid(url)
req = QNetworkRequest(url)
reply = page.networkAccessManager().get(req)
self.fetch(reply)
@ -362,7 +360,7 @@ class DownloadManager(QObject):
try:
download = self.downloads[count - 1]
except IndexError:
raise CommandError("There's no download {}!".format(count))
raise cmdexc.CommandError("There's no download {}!".format(count))
download.cancel()
@pyqtSlot('QNetworkReply')
@ -372,25 +370,27 @@ class DownloadManager(QObject):
Args:
reply: The QNetworkReply to download.
"""
_inline, suggested_filename = parse_content_disposition(reply)
_inline, suggested_filename = http.parse_content_disposition(reply)
logger.debug("fetch: {} -> {}".format(reply.url(), suggested_filename))
download = DownloadItem(reply, self)
download.finished.connect(partial(self.on_finished, download))
download.data_changed.connect(partial(self.on_data_changed, download))
download.finished.connect(
functools.partial(self.on_finished, download))
download.data_changed.connect(
functools.partial(self.on_data_changed, download))
download.error.connect(self.on_error)
download.basename = suggested_filename
self.download_about_to_be_added.emit(len(self.downloads) + 1)
self.downloads.append(download)
self.download_added.emit()
q = Question(self)
q = usertypes.Question(self)
q.text = "Save file to:"
q.mode = PromptMode.text
q.mode = usertypes.PromptMode.text
q.default = suggested_filename
q.answered.connect(download.set_filename)
q.cancelled.connect(download.cancel)
q.completed.connect(q.deleteLater)
q.destroyed.connect(partial(self.questions.remove, q))
q.destroyed.connect(functools.partial(self.questions.remove, q))
self.questions.append(q)
download.cancelled.connect(q.abort)
message.instance().ask(q, blocking=False)

View File

@ -21,28 +21,28 @@
import math
import subprocess
from collections import namedtuple
import collections
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QEvent, Qt, QUrl
from PyQt5.QtGui import QMouseEvent, QClipboard
from PyQt5.QtWidgets import QApplication
import qutebrowser.config.config as config
import qutebrowser.keyinput.modeman as modeman
import qutebrowser.utils.message as message
import qutebrowser.utils.webelem as webelem
import qutebrowser.commands.userscripts as userscripts
from qutebrowser.commands.exceptions import CommandError
from qutebrowser.utils.usertypes import enum, KeyMode
from qutebrowser.config import config
from qutebrowser.keyinput import modeman
from qutebrowser.utils import message, webelem
from qutebrowser.commands import userscripts
from qutebrowser.commands import exceptions as cmdexc
from qutebrowser.utils import usertypes
from qutebrowser.utils import qt as qtutils
from qutebrowser.utils.log import hints as logger
from qutebrowser.utils.qt import qt_ensure_valid
ElemTuple = namedtuple('ElemTuple', 'elem, label')
ElemTuple = collections.namedtuple('ElemTuple', 'elem, label')
Target = enum('Target', 'normal', 'tab', 'tab_bg', 'yank', 'yank_primary',
'fill', 'rapid', 'download', 'userscript', 'spawn')
Target = usertypes.enum('Target', 'normal', 'tab', 'tab_bg', 'yank',
'yank_primary', 'fill', 'rapid', 'download',
'userscript', 'spawn')
class HintContext:
@ -340,7 +340,7 @@ class HintManager(QObject):
Args:
url: The URL to open as a QURL.
"""
qt_ensure_valid(url)
qtutils.qt_ensure_valid(url)
sel = self._context.target == Target.yank_primary
mode = QClipboard.Selection if sel else QClipboard.Clipboard
urlstr = url.toString(QUrl.FullyEncoded | QUrl.RemovePassword)
@ -354,7 +354,7 @@ class HintManager(QObject):
Args:
url: The URL to open as a QUrl.
"""
qt_ensure_valid(url)
qtutils.qt_ensure_valid(url)
urlstr = url.toDisplayString(QUrl.FullyEncoded)
args = self._context.get_args(urlstr)
message.set_cmd_text(' '.join(args))
@ -370,19 +370,19 @@ class HintManager(QObject):
message.error("No suitable link found for this element.",
immediately=True)
return
qt_ensure_valid(url)
qtutils.qt_ensure_valid(url)
self.download_get.emit(url, elem.webFrame().page())
def _call_userscript(self, url):
"""Call an userscript from a hint."""
qt_ensure_valid(url)
qtutils.qt_ensure_valid(url)
cmd = self._context.args[0]
args = self._context.args[1:]
userscripts.run(cmd, *args, url=url)
def _spawn(self, url):
"""Spawn a simple command from a hint."""
qt_ensure_valid(url)
qtutils.qt_ensure_valid(url)
urlstr = url.toString(QUrl.FullyEncoded | QUrl.RemovePassword)
args = self._context.get_args(urlstr)
subprocess.Popen(args)
@ -406,7 +406,7 @@ class HintManager(QObject):
url = QUrl(text)
if url.isRelative():
url = baseurl.resolved(url)
qt_ensure_valid(url)
qtutils.qt_ensure_valid(url)
return url
def _find_prevnext(self, frame, prev=False):
@ -457,11 +457,11 @@ class HintManager(QObject):
"""
elem = self._find_prevnext(frame, prev)
if elem is None:
raise CommandError("No {} links found!".format(
raise cmdexc.CommandError("No {} links found!".format(
"prev" if prev else "forward"))
url = self._resolve_url(elem, baseurl)
if url is None or not url.isValid():
raise CommandError("No {} links found!".format(
raise cmdexc.CommandError("No {} links found!".format(
"prev" if prev else "forward"))
self.openurl.emit(url, newtab)
@ -488,12 +488,13 @@ class HintManager(QObject):
raise ValueError("start() was called with frame=None")
if target in (Target.userscript, Target.spawn, Target.fill):
if not args:
raise CommandError("Additional arguments are required with "
"target userscript/spawn/fill.")
raise cmdexc.CommandError(
"Additional arguments are required with target "
"userscript/spawn/fill.")
else:
if args:
raise CommandError("Arguments are only allowed with target "
"userscript/spawn.")
raise cmdexc.CommandError(
"Arguments are only allowed with target userscript/spawn.")
elems = []
ctx = HintContext()
ctx.frames = webelem.get_child_frames(mainframe)
@ -503,7 +504,7 @@ class HintManager(QObject):
visible_elems = [e for e in elems if filterfunc(e) and
webelem.is_visible(e, mainframe)]
if not visible_elems:
raise CommandError("No elements found.")
raise cmdexc.CommandError("No elements found.")
ctx.target = target
ctx.baseurl = baseurl
ctx.args = args
@ -516,7 +517,7 @@ class HintManager(QObject):
self._connect_frame_signals()
self.hint_strings_updated.emit(strings)
try:
modeman.enter(KeyMode.hint, 'HintManager.start')
modeman.enter(usertypes.KeyMode.hint, 'HintManager.start')
except modeman.ModeLockedError:
self._cleanup()
@ -560,7 +561,7 @@ class HintManager(QObject):
visible[k] = e
if not visible:
# Whoops, filtered all hints
modeman.leave(KeyMode.hint, 'all filtered')
modeman.leave(usertypes.KeyMode.hint, 'all filtered')
elif len(visible) == 1 and config.get('hints', 'auto-follow'):
# unpacking gets us the first (and only) key in the dict.
self.fire(*visible)
@ -606,12 +607,12 @@ class HintManager(QObject):
else:
raise ValueError("No suitable handler found!")
if self._context.target != Target.rapid:
modeman.maybe_leave(KeyMode.hint, 'followed')
modeman.maybe_leave(usertypes.KeyMode.hint, 'followed')
def follow_hint(self):
"""Follow the currently selected hint."""
if not self._context.to_follow:
raise CommandError("No hint to follow")
raise cmdexc.CommandError("No hint to follow")
self.fire(self._context.to_follow, force=True)
@pyqtSlot('QSize')
@ -627,16 +628,16 @@ class HintManager(QObject):
css = self._get_hint_css(elems.elem, elems.label)
elems.label.setAttribute('style', css)
@pyqtSlot(KeyMode)
@pyqtSlot(usertypes.KeyMode)
def on_mode_entered(self, mode):
"""Stop hinting when insert mode was entered."""
if mode == KeyMode.insert:
modeman.maybe_leave(KeyMode.hint, 'insert mode')
if mode == usertypes.KeyMode.insert:
modeman.maybe_leave(usertypes.KeyMode.hint, 'insert mode')
@pyqtSlot(KeyMode)
@pyqtSlot(usertypes.KeyMode)
def on_mode_left(self, mode):
"""Stop hinting when hinting mode was left."""
if mode != KeyMode.hint or self._context is None:
if mode != usertypes.KeyMode.hint or self._context is None:
# We have one HintManager per tab, so when this gets called,
# self._context might be None, because the current tab is not
# hinting.

View File

@ -24,29 +24,28 @@ OrderedDict. This is because we read them from a file at start and write them
to a file on shutdown, so it makes semse to keep them as strings her.e
"""
from functools import partial
from collections import OrderedDict
import functools
import collections
from PyQt5.QtCore import QStandardPaths, QUrl
import qutebrowser.utils.message as message
import qutebrowser.commands.utils as cmdutils
from qutebrowser.utils.usertypes import PromptMode
from qutebrowser.config.lineparser import LineConfigParser
from qutebrowser.utils.misc import get_standard_dir
from qutebrowser.utils.qt import qt_ensure_valid
from qutebrowser.commands.exceptions import CommandError
from qutebrowser.utils import message, usertypes
from qutebrowser.utils import misc as utils
from qutebrowser.utils import qt as qtutils
from qutebrowser.commands import utils as cmdutils
from qutebrowser.commands import exceptions as cmdexc
from qutebrowser.config import lineparser
marks = OrderedDict()
marks = collections.OrderedDict()
linecp = None
def init():
"""Read quickmarks from the config file."""
global linecp
confdir = get_standard_dir(QStandardPaths.ConfigLocation)
linecp = LineConfigParser(confdir, 'quickmarks')
confdir = utils.get_standard_dir(QStandardPaths.ConfigLocation)
linecp = lineparser.LineConfigParser(confdir, 'quickmarks')
for line in linecp:
try:
key, url = line.split(maxsplit=1)
@ -68,10 +67,10 @@ def prompt_save(url):
Args:
url: The quickmark url as a QUrl.
"""
qt_ensure_valid(url)
qtutils.qt_ensure_valid(url)
urlstr = url.toString(QUrl.RemovePassword | QUrl.FullyEncoded)
message.ask_async("Add quickmark:", PromptMode.text,
partial(quickmark_add, urlstr))
message.ask_async("Add quickmark:", usertypes.PromptMode.text,
functools.partial(quickmark_add, urlstr))
@cmdutils.register()
@ -83,9 +82,9 @@ def quickmark_add(urlstr, name):
name: The name for the new quickmark.
"""
if not name:
raise CommandError("Can't set mark with empty name!")
raise cmdexc.CommandError("Can't set mark with empty name!")
if not urlstr:
raise CommandError("Can't set mark with empty URL!")
raise cmdexc.CommandError("Can't set mark with empty URL!")
def set_mark():
"""Really set the quickmark."""
@ -101,10 +100,12 @@ def quickmark_add(urlstr, name):
def get(name):
"""Get the URL of the quickmark named name as a QUrl."""
if name not in marks:
raise CommandError("Quickmark '{}' does not exist!".format(name))
raise cmdexc.CommandError(
"Quickmark '{}' does not exist!".format(name))
urlstr = marks[name]
url = QUrl(urlstr)
if not url.isValid():
raise CommandError("Invalid URL for quickmark {}: {} ({})".format(
name, urlstr, url.errorString()))
raise cmdexc.CommandError(
"Invalid URL for quickmark {}: {} ({})".format(name, urlstr,
url.errorString()))
return url

View File

@ -19,12 +19,12 @@
"""A filter for signals which either filters or passes them."""
from functools import partial
import functools
from PyQt5.QtCore import QObject
from qutebrowser.utils.debug import dbg_signal, signal_name
from qutebrowser.widgets.webview import WebView
from qutebrowser.utils import debug
from qutebrowser.widgets import webview
from qutebrowser.utils.log import signals as logger
@ -58,10 +58,10 @@ class SignalFilter(QObject):
Return:
A partial functon calling _filter_signals with a signal.
"""
if not isinstance(tab, WebView):
if not isinstance(tab, webview.WebView):
raise ValueError("Tried to create filter for {} which is no "
"WebView!".format(tab))
return partial(self._filter_signals, signal, tab)
return functools.partial(self._filter_signals, signal, tab)
def _filter_signals(self, signal, tab, *args):
"""Filter signals and trigger TabbedBrowser signals if needed.
@ -80,7 +80,7 @@ class SignalFilter(QObject):
Emit:
The target signal if the sender was the current widget.
"""
log_signal = signal_name(signal) not in self.BLACKLIST
log_signal = debug.signal_name(signal) not in self.BLACKLIST
try:
tabidx = self._tabs.indexOf(tab)
except RuntimeError:
@ -89,9 +89,9 @@ class SignalFilter(QObject):
if tabidx == self._tabs.currentIndex():
if log_signal:
logger.debug("emitting: {} (tab {})".format(
dbg_signal(signal, args), tabidx))
debug.dbg_signal(signal, args), tabidx))
signal.emit(*args)
else:
if log_signal:
logger.debug("ignoring: {} (tab {})".format(
dbg_signal(signal, args), tabidx))
debug.dbg_signal(signal, args), tabidx))

View File

@ -28,14 +28,11 @@ from PyQt5.QtWidgets import QFileDialog
from PyQt5.QtPrintSupport import QPrintDialog
from PyQt5.QtWebKitWidgets import QWebPage
import qutebrowser.utils.message as message
import qutebrowser.config.config as config
import qutebrowser.utils.log as log
import qutebrowser.utils.http as http
from qutebrowser.network.networkmanager import NetworkManager
from qutebrowser.utils.misc import read_file
from qutebrowser.utils.qt import check_print_compat
from qutebrowser.utils.usertypes import PromptMode, ClickTarget
from qutebrowser.config import config
from qutebrowser.network import networkmanager
from qutebrowser.utils import message, usertypes, log, http
from qutebrowser.utils import misc as utils
from qutebrowser.utils import qt as qtutils
class BrowserPage(QWebPage):
@ -61,7 +58,7 @@ class BrowserPage(QWebPage):
QWebPage.ErrorPageExtension: self._handle_errorpage,
QWebPage.ChooseMultipleFilesExtension: self._handle_multiple_files,
}
self._networkmanager = NetworkManager(self)
self._networkmanager = networkmanager.NetworkManager(self)
self.setNetworkAccessManager(self._networkmanager)
self.setForwardUnsupportedContent(True)
self.printRequested.connect(self.on_print_requested)
@ -83,7 +80,8 @@ class BrowserPage(QWebPage):
http://www.riverbankcomputing.com/pipermail/pyqt/2014-June/034385.html
"""
answer = message.ask("js: {}".format(msg), PromptMode.text, default)
answer = message.ask("js: {}".format(msg), usertypes.PromptMode.text,
default)
if answer is None:
return (False, "")
else:
@ -122,7 +120,7 @@ class BrowserPage(QWebPage):
log.webview.debug("Error domain: {}, error code: {}".format(
info.domain, info.error))
title = "Error loading page: {}".format(urlstr)
errpage.content = read_file('html/error.html').format(
errpage.content = utils.read_file('html/error.html').format(
title=title, url=urlstr, error=info.errorString, icon='')
return True
@ -158,7 +156,7 @@ class BrowserPage(QWebPage):
def on_print_requested(self, frame):
"""Handle printing when requested via javascript."""
if not check_print_compat():
if not qtutils.check_print_compat():
message.error("Printing on Qt < 5.3.0 on Windows is broken, "
"please upgrade!", immediately=True)
return
@ -246,11 +244,12 @@ class BrowserPage(QWebPage):
def javaScriptAlert(self, _frame, msg):
"""Override javaScriptAlert to use the statusbar."""
message.ask("[js alert] {}".format(msg), PromptMode.alert)
message.ask("[js alert] {}".format(msg), usertypes.PromptMode.alert)
def javaScriptConfirm(self, _frame, msg):
"""Override javaScriptConfirm to use the statusbar."""
ans = message.ask("[js confirm] {}".format(msg), PromptMode.yesno)
ans = message.ask("[js confirm] {}".format(msg),
usertypes.PromptMode.yesno)
return bool(ans)
def javaScriptConsoleMessage(self, msg, line, source):
@ -270,7 +269,7 @@ class BrowserPage(QWebPage):
def shouldInterruptJavaScript(self):
"""Override shouldInterruptJavaScript to use the statusbar."""
answer = message.ask("Interrupt long-running javascript?",
PromptMode.yesno)
usertypes.PromptMode.yesno)
if answer is None:
answer = True
return answer
@ -298,10 +297,10 @@ class BrowserPage(QWebPage):
message.error("Invalid link {} clicked!".format(urlstr))
log.webview.debug(url.errorString())
return False
if self._view.open_target == ClickTarget.tab:
if self._view.open_target == usertypes.ClickTarget.tab:
self._view.tabbedbrowser.tabopen(url, False)
return False
elif self._view.open_target == ClickTarget.tab_bg:
elif self._view.open_target == usertypes.ClickTarget.tab_bg:
self._view.tabbedbrowser.tabopen(url, True)
return False
else:

View File

@ -22,9 +22,8 @@
from PyQt5.QtCore import QCoreApplication, QUrl
from PyQt5.QtWebKit import QWebSettings
from qutebrowser.commands.exceptions import (ArgumentCountError,
PrerequisitesError)
from qutebrowser.utils.misc import dotted_getattr
from qutebrowser.commands import exceptions as cmdexc
from qutebrowser.utils import misc as utils
from qutebrowser.utils.log import commands as logger
@ -84,16 +83,18 @@ class Command:
curmode = QCoreApplication.instance().modeman.mode
if self.modes is not None and curmode not in self.modes:
mode_names = '/'.join(mode.name for mode in self.modes)
raise PrerequisitesError("{}: This command is only allowed in {} "
"mode.".format(self.name, mode_names))
raise cmdexc.PrerequisitesError(
"{}: This command is only allowed in {} mode.".format(
self.name, mode_names))
elif self.not_modes is not None and curmode in self.not_modes:
mode_names = '/'.join(mode.name for mode in self.not_modes)
raise PrerequisitesError("{}: This command is not allowed in {} "
"mode.".format(self.name, mode_names))
raise cmdexc.PrerequisitesError(
"{}: This command is not allowed in {} mode.".format(
self.name, mode_names))
if self.needs_js and not QWebSettings.globalSettings().testAttribute(
QWebSettings.JavascriptEnabled):
raise PrerequisitesError("{}: This command needs javascript "
"enabled.".format(self.name))
raise cmdexc.PrerequisitesError(
"{}: This command needs javascript enabled.".format(self.name))
if self.nargs[1] is None and self.nargs[0] <= len(args):
pass
elif self.nargs[0] <= len(args) <= self.nargs[1]:
@ -105,8 +106,9 @@ class Command:
argcnt = '{}-inf'.format(self.nargs[0])
else:
argcnt = '{}-{}'.format(self.nargs[0], self.nargs[1])
raise ArgumentCountError("{}: {} args expected, but got {}".format(
self.name, argcnt, len(args)))
raise cmdexc.ArgumentCountError(
"{}: {} args expected, but got {}".format(self.name, argcnt,
len(args)))
def run(self, args=None, count=None):
"""Run the command.
@ -142,7 +144,7 @@ class Command:
if self.instance == '':
obj = app
else:
obj = dotted_getattr(app, self.instance)
obj = utils.dotted_getattr(app, self.instance)
new_args.insert(0, obj)
if count is not None and self.count:

View File

@ -22,12 +22,11 @@
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject
from PyQt5.QtWebKitWidgets import QWebPage
import qutebrowser.config.config as config
import qutebrowser.commands.utils as cmdutils
import qutebrowser.utils.message as message
from qutebrowser.commands.exceptions import (NoSuchCommandError,
CommandMetaError, CommandError)
from qutebrowser.utils.misc import safe_shlex_split
from qutebrowser.config import config
from qutebrowser.commands import utils as cmdutils
from qutebrowser.commands import exceptions as cmdexc
from qutebrowser.utils import message
from qutebrowser.utils import misc as utils
from qutebrowser.utils.log import commands as logger
@ -201,7 +200,7 @@ class CommandRunner:
"""
parts = text.strip().split(maxsplit=1)
if not parts:
raise NoSuchCommandError("No command given")
raise cmdexc.NoSuchCommandError("No command given")
cmdstr = parts[0]
if aliases:
new_cmd = self._get_alias(text, alias_no_args)
@ -217,11 +216,12 @@ class CommandRunner:
parts.append('')
return parts
else:
raise NoSuchCommandError('{}: no such command'.format(cmdstr))
raise cmdexc.NoSuchCommandError(
'{}: no such command'.format(cmdstr))
if len(parts) == 1:
args = []
elif cmd.split:
args = safe_shlex_split(parts[1])
args = utils.safe_shlex_split(parts[1])
else:
args = parts[1].split(maxsplit=cmd.nargs[0] - 1)
self._cmd = cmd
@ -266,7 +266,7 @@ class CommandRunner:
"""Run a command and display exceptions in the statusbar."""
try:
self.run(text, count)
except (CommandMetaError, CommandError) as e:
except (cmdexc.CommandMetaError, cmdexc.CommandError) as e:
message.error(e, immediately=True)
@pyqtSlot(str, int)
@ -277,5 +277,5 @@ class CommandRunner:
suitable to use while initializing."""
try:
self.run(text, count)
except (CommandMetaError, CommandError) as e:
except (cmdexc.CommandMetaError, cmdexc.CommandError) as e:
message.error(e)

View File

@ -26,17 +26,17 @@ Module attributes:
import os
import os.path
import tempfile
from select import select
from functools import partial
import select
import functools
from PyQt5.QtCore import (pyqtSignal, QObject, QThread, QStandardPaths,
QProcessEnvironment, QProcess, QUrl)
import qutebrowser.utils.message as message
from qutebrowser.utils.misc import get_standard_dir
from qutebrowser.utils import message
from qutebrowser.utils import misc as utils
from qutebrowser.utils.log import procs as logger
from qutebrowser.commands.exceptions import CommandError
from qutebrowser.commands.runners import CommandRunner
from qutebrowser.commands import runners
from qutebrowser.commands import exceptions as cmdexc
_runners = []
@ -83,7 +83,7 @@ class _BlockingFIFOReader(QObject):
self.fifo = os.fdopen(fd, 'r')
while True:
logger.debug("thread loop")
ready_r, _ready_w, _ready_e = select([self.fifo], [], [], 1)
ready_r, _ready_w, _ready_e = select.select([self.fifo], [], [], 1)
if ready_r:
logger.debug("reading data")
for line in self.fifo:
@ -205,7 +205,7 @@ class _POSIXUserscriptRunner(_BaseUserscriptRunner):
self.thread = None
def run(self, cmd, *args, env=None):
rundir = get_standard_dir(QStandardPaths.RuntimeLocation)
rundir = utils.get_standard_dir(QStandardPaths.RuntimeLocation)
# tempfile.mktemp is deprecated and discouraged, but we use it here to
# create a FIFO since the only other alternative would be to create a
# directory and place the FIFO there, which sucks. Since os.kfifo will
@ -313,7 +313,8 @@ class _DummyUserscriptRunner:
def run(self, _cmd, *_args, _env=None):
"""Print an error as userscripts are not supported."""
self.finished.emit()
raise CommandError("Userscripts are not supported on this platform!")
raise cmdexc.CommandError(
"Userscripts are not supported on this platform!")
# Here we basically just assign a generic UserscriptRunner class which does the
@ -329,7 +330,7 @@ else:
def init():
"""Initialize the global _commandrunner."""
global _commandrunner
_commandrunner = CommandRunner()
_commandrunner = runners.CommandRunner()
def run(cmd, *args, url):
@ -341,4 +342,4 @@ def run(cmd, *args, url):
runner.got_cmd.connect(_commandrunner.run_safely)
runner.run(cmd, *args, env={'QUTE_URL': urlstr})
_runners.append(runner)
runner.finished.connect(partial(_runners.remove, runner))
runner.finished.connect(functools.partial(_runners.remove, runner))

View File

@ -24,12 +24,12 @@ Module attributes:
"""
import inspect
from collections import Iterable
import collections
import qutebrowser.utils.qt as qtutils
from qutebrowser.commands.command import Command
from qutebrowser.commands.exceptions import CommandError
from qutebrowser.utils.usertypes import KeyMode
from qutebrowser.utils import usertypes
from qutebrowser.utils import qt as qtutils
from qutebrowser.commands import command
from qutebrowser.commands import exceptions as cmdexc
cmd_dict = {}
@ -49,8 +49,9 @@ def check_overflow(arg, ctype):
try:
qtutils.check_overflow(arg, ctype)
except OverflowError:
raise CommandError("Numeric argument is too large for internal {} "
"representation.".format(ctype))
raise cmdexc.CommandError(
"Numeric argument is too large for internal {} "
"representation.".format(ctype))
def arg_or_count(arg, count, default=None, countzero=None):
@ -135,11 +136,11 @@ class register: # pylint: disable=invalid-name
self.debug = debug
if modes is not None:
for m in modes:
if not isinstance(m, KeyMode):
if not isinstance(m, usertypes.KeyMode):
raise TypeError("Mode {} is no KeyMode member!".format(m))
if not_modes is not None:
for m in not_modes:
if not isinstance(m, KeyMode):
if not isinstance(m, usertypes.KeyMode):
raise TypeError("Mode {} is no KeyMode member!".format(m))
def __call__(self, func):
@ -178,12 +179,11 @@ class register: # pylint: disable=invalid-name
desc = func.__doc__.splitlines()[0].strip()
else:
desc = ""
cmd = Command(name=mainname, split=self.split,
hide=self.hide, nargs=nargs, count=count, desc=desc,
instance=self.instance, handler=func,
completion=self.completion, modes=self.modes,
not_modes=self.not_modes, needs_js=self.needs_js,
debug=self.debug)
cmd = command.Command(
name=mainname, split=self.split, hide=self.hide, nargs=nargs,
count=count, desc=desc, instance=self.instance, handler=func,
completion=self.completion, modes=self.modes,
not_modes=self.not_modes, needs_js=self.needs_js, debug=self.debug)
for name in names:
cmd_dict[name] = cmd
return func
@ -209,7 +209,7 @@ class register: # pylint: disable=invalid-name
# we assume count always has a default (and it should!)
if self.nargs is not None:
# If nargs is overriden, use that.
if isinstance(self.nargs, Iterable):
if isinstance(self.nargs, collections.Iterable):
# Iterable (min, max)
# pylint: disable=unpacking-non-sequence
minargs, maxargs = self.nargs

View File

@ -28,18 +28,15 @@ import os
import os.path
import textwrap
import configparser
from configparser import ExtendedInterpolation
from collections.abc import MutableMapping
import collections.abc
from PyQt5.QtCore import pyqtSignal, QObject, QCoreApplication
import qutebrowser.config.configdata as configdata
import qutebrowser.commands.utils as cmdutils
import qutebrowser.utils.message as message
import qutebrowser.utils.log as log
from qutebrowser.config.iniparsers import ReadConfigParser
from qutebrowser.config.conftypes import ValidationError
from qutebrowser.commands.exceptions import CommandError
from qutebrowser.utils import log
from qutebrowser.config import configdata, iniparsers, conftypes
from qutebrowser.commands import utils as cmdutils
from qutebrowser.commands import exceptions as cmdexc
from qutebrowser.utils import message
from qutebrowser.utils.usertypes import Completion
@ -114,7 +111,7 @@ class ConfigManager(QObject):
def __init__(self, configdir, fname, parent=None):
super().__init__(parent)
self.sections = configdata.DATA
self._configparser = ReadConfigParser(configdir, fname)
self._configparser = iniparsers.ReadConfigParser(configdir, fname)
self._configfile = os.path.join(configdir, fname)
self._wrapper_args = {
'width': 72,
@ -124,7 +121,7 @@ class ConfigManager(QObject):
}
self._configdir = configdir
self._fname = fname
self._interpolation = ExtendedInterpolation()
self._interpolation = configparser.ExtendedInterpolation()
self._proxies = {}
for sectname in self.sections.keys():
self._proxies[sectname] = SectionProxy(self, sectname)
@ -227,7 +224,7 @@ class ConfigManager(QObject):
k = k.replace('<eq>', '=')
try:
self.set('conf', sectname, k, v)
except ValidationError as e:
except conftypes.ValidationError as e:
e.section = sectname
e.option = k
raise
@ -299,7 +296,8 @@ class ConfigManager(QObject):
try:
val = self.get(sectname, optname, transformed=False)
except (NoOptionError, NoSectionError) as e:
raise CommandError("get: {} - {}".format(e.__class__.__name__, e))
raise cmdexc.CommandError("get: {} - {}".format(
e.__class__.__name__, e))
else:
message.info("{} {} = {}".format(sectname, optname, val),
immediately=True)
@ -350,9 +348,10 @@ class ConfigManager(QObject):
"""
try:
self.set('conf', sectname, optname, value)
except (NoOptionError, NoSectionError, ValidationError,
except (NoOptionError, NoSectionError, conftypes.ValidationError,
ValueError) as e:
raise CommandError("set: {} - {}".format(e.__class__.__name__, e))
raise cmdexc.CommandError("set: {} - {}".format(
e.__class__.__name__, e))
@cmdutils.register(name='set-temp', instance='config',
completion=[Completion.section, Completion.option,
@ -371,8 +370,9 @@ class ConfigManager(QObject):
"""
try:
self.set('temp', sectname, optname, value)
except (NoOptionError, NoSectionError, ValidationError) as e:
raise CommandError("set: {} - {}".format(e.__class__.__name__, e))
except (NoOptionError, NoSectionError, conftypes.ValidationError) as e:
raise cmdexc.CommandError("set: {} - {}".format(
e.__class__.__name__, e))
def set(self, layer, sectname, optname, value):
"""Set an option.
@ -442,7 +442,7 @@ class ConfigManager(QObject):
return val
class SectionProxy(MutableMapping):
class SectionProxy(collections.abc.MutableMapping):
"""A proxy for a single section from a config.

View File

@ -27,11 +27,11 @@ DATA: The config defaults, an OrderedDict of sections.
"""
import re
from collections import OrderedDict
import collections
from qutebrowser.config import conftypes as typ
from qutebrowser.config import sections as sect
from qutebrowser.config.value import SettingValue
import qutebrowser.config.conftypes as types
import qutebrowser.config.sections as sect
from qutebrowser.utils.qt import MAXVALS
@ -165,57 +165,57 @@ SECTION_DESC = {
}
DATA = OrderedDict([
DATA = collections.OrderedDict([
('general', sect.KeyValue(
('ignore-case',
SettingValue(types.IgnoreCase(), 'smart'),
SettingValue(typ.IgnoreCase(), 'smart'),
"Whether to find text on a page case-insensitively."),
('wrap-search',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether to wrap finding text to the top when arriving at the end."),
('startpage',
SettingValue(types.List(), 'http://www.duckduckgo.com'),
SettingValue(typ.List(), 'http://www.duckduckgo.com'),
"The default page(s) to open at the start, separated by commas."),
('auto-search',
SettingValue(types.AutoSearch(), 'naive'),
SettingValue(typ.AutoSearch(), 'naive'),
"Whether to start a search when something else than a URL is "
"entered."),
('auto-save-config',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether to save the config automatically on quit."),
('editor',
SettingValue(types.ShellCommand(placeholder=True), 'gvim -f "{}"'),
SettingValue(typ.ShellCommand(placeholder=True), 'gvim -f "{}"'),
"The editor (and arguments) to use for the `open-editor` command.\n\n"
"Use `{}` for the filename. The value gets split like in a shell, so "
"you can use `\"` or `'` to quote arguments."),
('editor-encoding',
SettingValue(types.Encoding(), 'utf-8'),
SettingValue(typ.Encoding(), 'utf-8'),
"Encoding to use for editor."),
('private-browsing',
SettingValue(types.Bool(), 'false'),
SettingValue(typ.Bool(), 'false'),
"Do not record visited pages in the history or store web page "
"icons."),
('developer-extras',
SettingValue(types.Bool(), 'false'),
SettingValue(typ.Bool(), 'false'),
"Enable extra tools for Web developers.\n\n"
"This needs to be enabled for `:inspector` to work and also adds an "
"_Inspect_ entry to the context menu."),
('print-element-backgrounds',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether the background color and images are also drawn when the "
"page is printed."),
('xss-auditing',
SettingValue(types.Bool(), 'false'),
SettingValue(typ.Bool(), 'false'),
"Whether load requests should be monitored for cross-site scripting "
"attempts.\n\n"
"Suspicious scripts will be blocked and reported in the inspector's "
@ -223,11 +223,11 @@ DATA = OrderedDict([
"performance."),
('site-specific-quirks',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Enable workarounds for broken sites."),
('default-encoding',
SettingValue(types.String(none_ok=True), ''),
SettingValue(typ.String(none_ok=True), ''),
"Default encoding to use for websites.\n\n"
"The encoding must be a string describing an encoding such as "
'_utf-8_, _iso-8859-1_, etc. If left empty a default value will be '
@ -236,126 +236,125 @@ DATA = OrderedDict([
('ui', sect.KeyValue(
('zoom-levels',
SettingValue(types.PercList(minval=0),
SettingValue(typ.PercList(minval=0),
'25%,33%,50%,67%,75%,90%,100%,110%,125%,150%,175%,200%,'
'250%,300%,400%,500%'),
"The available zoom levels, separated by commas."),
('default-zoom',
SettingValue(types.ZoomPerc(), '100%'),
SettingValue(typ.ZoomPerc(), '100%'),
"The default zoom level."),
('message-timeout',
SettingValue(types.Int(), '2000'),
SettingValue(typ.Int(), '2000'),
"Time (in ms) to show messages in the statusbar for."),
('confirm-quit',
SettingValue(types.ConfirmQuit(), 'never'),
SettingValue(typ.ConfirmQuit(), 'never'),
"Whether to confirm quitting the application."),
('display-statusbar-messages',
SettingValue(types.Bool(), 'false'),
SettingValue(typ.Bool(), 'false'),
"Whether to display javascript statusbar messages."),
('zoom-text-only',
SettingValue(types.Bool(), 'false'),
SettingValue(typ.Bool(), 'false'),
"Whether the zoom factor on a frame applies only to the text or to "
"all content."),
('frame-flattening',
SettingValue(types.Bool(), 'false'),
SettingValue(typ.Bool(), 'false'),
"Whether to expand each subframe to its contents.\n\n"
"This will flatten all the frames to become one scrollable page."),
('user-stylesheet',
SettingValue(types.WebSettingsFile(), ''),
SettingValue(typ.WebSettingsFile(), ''),
"User stylesheet to use."),
('css-media-type',
SettingValue(types.String(none_ok=True), ''),
SettingValue(typ.String(none_ok=True), ''),
"Set the CSS media type."),
)),
('network', sect.KeyValue(
('do-not-track',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Value to send in the `DNT` header."),
('accept-language',
SettingValue(types.String(none_ok=True), 'en-US,en'),
SettingValue(typ.String(none_ok=True), 'en-US,en'),
"Value to send in the `accept-language` header."),
('user-agent',
SettingValue(types.String(none_ok=True), ''),
SettingValue(typ.String(none_ok=True), ''),
"User agent to send. Empty to send the default."),
('proxy',
SettingValue(types.Proxy(), 'system'),
SettingValue(typ.Proxy(), 'system'),
"The proxy to use.\n\n"
"In addition to the listed values, you can use a `socks://...` or "
"`http://...` URL."),
('ssl-strict',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether to validate SSL handshakes."),
('dns-prefetch',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether to try to pre-fetch DNS entries to speed up browsing."),
)),
('completion', sect.KeyValue(
('show',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether to show the autocompletion window."),
('height',
SettingValue(types.PercOrInt(minperc=0, maxperc=100, minint=1),
'50%'),
SettingValue(typ.PercOrInt(minperc=0, maxperc=100, minint=1), '50%'),
"The height of the completion, in px or as percentage of the "
"window."),
('history-length',
SettingValue(types.Int(minval=-1), '100'),
SettingValue(typ.Int(minval=-1), '100'),
"How many commands to save in the history.\n\n"
"0: no history / -1: unlimited"),
('quick-complete',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether to move on to the next part when there's only one possible "
"completion left."),
('shrink',
SettingValue(types.Bool(), 'false'),
SettingValue(typ.Bool(), 'false'),
"Whether to shrink the completion to be smaller than the configured "
"size if there are no scrollbars."),
)),
('input', sect.KeyValue(
('timeout',
SettingValue(types.Int(minval=0, maxval=MAXVALS['int']), '500'),
SettingValue(typ.Int(minval=0, maxval=MAXVALS['int']), '500'),
"Timeout for ambiguous keybindings."),
('insert-mode-on-plugins',
SettingValue(types.Bool(), 'false'),
SettingValue(typ.Bool(), 'false'),
"Whether to switch to insert mode when clicking flash and other "
"plugins."),
('auto-leave-insert-mode',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether to leave insert mode if a non-editable element is clicked."),
('auto-insert-mode',
SettingValue(types.Bool(), 'false'),
SettingValue(typ.Bool(), 'false'),
"Whether to automatically enter insert mode if an editable element "
"is focused after page load."),
('forward-unbound-keys',
SettingValue(types.ForwardUnboundKeys(), 'auto'),
SettingValue(typ.ForwardUnboundKeys(), 'auto'),
"Whether to forward unbound keys to the webview in normal mode."),
('spatial-navigation',
SettingValue(types.Bool(), 'false'),
SettingValue(typ.Bool(), 'false'),
"Enables or disables the Spatial Navigation feature\n\n"
"Spatial navigation consists in the ability to navigate between "
"focusable elements in a Web page, such as hyperlinks and form "
@ -365,76 +364,74 @@ DATA = OrderedDict([
"right and which element he probably wants."),
('links-included-in-focus-chain',
SettingValue(types.Bool(), 'true'),
"Whether hyperlinks should be included in the keyboard focus "
"chain."),
SettingValue(typ.Bool(), 'true'),
"Whether hyperlinks should be included in the keyboard focus chain."),
)),
('tabs', sect.KeyValue(
('background-tabs',
SettingValue(types.Bool(), 'false'),
SettingValue(typ.Bool(), 'false'),
"Whether to open new tabs (middleclick/ctrl+click) in background."),
('select-on-remove',
SettingValue(types.SelectOnRemove(), 'right'),
SettingValue(typ.SelectOnRemove(), 'right'),
"Which tab to select when the focused tab is removed."),
('new-tab-position',
SettingValue(types.NewTabPosition(), 'right'),
SettingValue(typ.NewTabPosition(), 'right'),
"How new tabs are positioned."),
('new-tab-position-explicit',
SettingValue(types.NewTabPosition(), 'last'),
SettingValue(typ.NewTabPosition(), 'last'),
"How new tabs opened explicitely are positioned."),
('last-close',
SettingValue(types.LastClose(), 'ignore'),
SettingValue(typ.LastClose(), 'ignore'),
"Behaviour when the last tab is closed."),
('wrap',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether to wrap when changing tabs."),
('movable',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether tabs should be movable."),
('close-mouse-button',
SettingValue(types.CloseButton(), 'middle'),
SettingValue(typ.CloseButton(), 'middle'),
"On which mouse button to close tabs."),
('position',
SettingValue(types.Position(), 'north'),
SettingValue(typ.Position(), 'north'),
"The position of the tab bar."),
('show-favicons',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether to show favicons in the tab bar."),
('width',
SettingValue(types.PercOrInt(minperc=0, maxperc=100, minint=1),
'20%'),
SettingValue(typ.PercOrInt(minperc=0, maxperc=100, minint=1), '20%'),
"The width of the tab bar if it's vertical, in px or as percentage "
"of the window."),
('indicator-width',
SettingValue(types.Int(minval=0), '3'),
SettingValue(typ.Int(minval=0), '3'),
"Width of the progress indicator (0 to disable)."),
('indicator-space',
SettingValue(types.Int(minval=0), '3'),
SettingValue(typ.Int(minval=0), '3'),
"Spacing between tab edge and indicator."),
)),
('storage', sect.KeyValue(
('download-directory',
SettingValue(types.Directory(none_ok=True), ''),
SettingValue(typ.Directory(none_ok=True), ''),
"The directory to save downloads to. An empty value selects a "
"sensible os-specific default."),
('maximum-pages-in-cache',
SettingValue(types.Int(none_ok=True, minval=0, maxval=MAXVALS['int']),
''),
SettingValue(
typ.Int(none_ok=True, minval=0, maxval=MAXVALS['int']), ''),
"The maximum number of pages to hold in the memory page cache.\n\n"
"The Page Cache allows for a nicer user experience when navigating "
"forth or back to pages in the forward/back history, by pausing and "
@ -443,8 +440,8 @@ DATA = OrderedDict([
"http://webkit.org/blog/427/webkit-page-cache-i-the-basics/"),
('object-cache-capacities',
SettingValue(types.WebKitBytesList(length=3, maxsize=MAXVALS['int']),
''),
SettingValue(
typ.WebKitBytesList(length=3, maxsize=MAXVALS['int']), ''),
"The capacities for the memory cache for dead objects such as "
"stylesheets or scripts. Syntax: cacheMinDeadCapacity, cacheMaxDead, "
"totalCapacity.\n\n"
@ -457,19 +454,19 @@ DATA = OrderedDict([
"that the cache should consume *overall*."),
('offline-storage-default-quota',
SettingValue(types.WebKitBytes(maxsize=MAXVALS['int64']), ''),
SettingValue(typ.WebKitBytes(maxsize=MAXVALS['int64']), ''),
"Default quota for new offline storage databases."),
('offline-web-application-cache-quota',
SettingValue(types.WebKitBytes(maxsize=MAXVALS['int64']), ''),
SettingValue(typ.WebKitBytes(maxsize=MAXVALS['int64']), ''),
"Quota for the offline web application cache."),
('offline-storage-database',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether support for the HTML 5 offline storage feature is enabled."),
('offline-web-application-storage',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether support for the HTML 5 web application cache feature is "
"enabled.\n\n"
"An application cache acts like an HTTP cache in some sense. For "
@ -480,96 +477,96 @@ DATA = OrderedDict([
"http://dev.w3.org/html5/spec/Overview.html#appcache"),
('local-storage',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether support for the HTML 5 local storage feature is enabled."),
)),
('permissions', sect.KeyValue(
('allow-images',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether images are automatically loaded in web pages."),
('allow-javascript',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Enables or disables the running of JavaScript programs."),
('allow-plugins',
SettingValue(types.Bool(), 'false'),
SettingValue(typ.Bool(), 'false'),
"Enables or disables plugins in Web pages.\n\n"
'Qt plugins with a mimetype such as "application/x-qt-plugin" are '
"not affected by this setting."),
#('allow-java',
# SettingValue(types.Bool(), 'true'),
# SettingValue(typ.Bool(), 'true'),
# "Enables or disables Java applets. Currently Java applets are "
# "not supported"),
('javascript-can-open-windows',
SettingValue(types.Bool(), 'false'),
SettingValue(typ.Bool(), 'false'),
"Whether JavaScript programs can open new windows."),
('javascript-can-close-windows',
SettingValue(types.Bool(), 'false'),
SettingValue(typ.Bool(), 'false'),
"Whether JavaScript programs can close windows."),
('javascript-can-access-clipboard',
SettingValue(types.Bool(), 'false'),
SettingValue(typ.Bool(), 'false'),
"Whether JavaScript programs can read or write to the clipboard."),
('local-content-can-access-remote-urls',
SettingValue(types.Bool(), 'false'),
SettingValue(typ.Bool(), 'false'),
"Whether locally loaded documents are allowed to access remote "
"urls."),
('local-content-can-access-file-urls',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether locally loaded documents are allowed to access other local "
"urls."),
('cookies-accept',
SettingValue(types.AcceptCookies(), 'default'),
SettingValue(typ.AcceptCookies(), 'default'),
"Whether to accept cookies."),
('cookies-store',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether to store cookies."),
)),
('hints', sect.KeyValue(
('border',
SettingValue(types.String(), '1px solid #E3BE23'),
SettingValue(typ.String(), '1px solid #E3BE23'),
"CSS border value for hints."),
('opacity',
SettingValue(types.Float(minval=0.0, maxval=1.0), '0.7'),
SettingValue(typ.Float(minval=0.0, maxval=1.0), '0.7'),
"Opacity for hints."),
('mode',
SettingValue(types.HintMode(), 'letter'),
SettingValue(typ.HintMode(), 'letter'),
"Mode to use for hints."),
('chars',
SettingValue(types.String(minlen=2), 'asdfghjkl'),
SettingValue(typ.String(minlen=2), 'asdfghjkl'),
"Chars used for hint strings."),
('auto-follow',
SettingValue(types.Bool(), 'true'),
SettingValue(typ.Bool(), 'true'),
"Whether to auto-follow a hint if there's only one left."),
('next-regexes',
SettingValue(types.RegexList(flags=re.IGNORECASE),
SettingValue(typ.RegexList(flags=re.IGNORECASE),
r'\bnext\b,\bmore\b,\bnewer\b,\b[>→≫]\b,\b(>>|»)\b'),
"A comma-separated list of regexes to use for 'next' links."),
('prev-regexes',
SettingValue(types.RegexList(flags=re.IGNORECASE),
SettingValue(typ.RegexList(flags=re.IGNORECASE),
r'\bprev(ious)?\b,\bback\b,\bolder\b,\b[<←≪]\b,'
r'\b(<<|«)\b'),
"A comma-separated list of regexes to use for 'prev' links."),
)),
('searchengines', sect.ValueList(
types.SearchEngineName(), types.SearchEngineUrl(),
typ.SearchEngineName(), typ.SearchEngineUrl(),
('DEFAULT', '${duckduckgo}'),
('duckduckgo', 'https://duckduckgo.com/?q={}'),
('ddg', '${duckduckgo}'),
@ -581,7 +578,7 @@ DATA = OrderedDict([
)),
('keybind', sect.ValueList(
types.KeyBindingName(), types.KeyBinding(),
typ.KeyBindingName(), typ.KeyBinding(),
('o', 'set-cmd-text ":open "'),
('go', 'set-cmd-text :open {url}'),
('O', 'set-cmd-text ":open-tab "'),
@ -674,7 +671,7 @@ DATA = OrderedDict([
)),
('keybind.insert', sect.ValueList(
types.KeyBindingName(), types.KeyBinding(),
typ.KeyBindingName(), typ.KeyBinding(),
('<Escape>', 'leave-mode'),
('<Ctrl-N>', 'leave-mode'),
('<Ctrl-E>', 'open-editor'),
@ -682,7 +679,7 @@ DATA = OrderedDict([
)),
('keybind.hint', sect.ValueList(
types.KeyBindingName(), types.KeyBinding(),
typ.KeyBindingName(), typ.KeyBinding(),
('<Return>', 'follow-hint'),
('<Escape>', 'leave-mode'),
('<Ctrl-N>', 'leave-mode'),
@ -690,7 +687,7 @@ DATA = OrderedDict([
)),
('keybind.passthrough', sect.ValueList(
types.KeyBindingName(), types.KeyBinding(),
typ.KeyBindingName(), typ.KeyBinding(),
('<Escape>', 'leave-mode'),
('<Ctrl-[>', '${<Escape>}'),
)),
@ -699,7 +696,7 @@ DATA = OrderedDict([
# text field.
('keybind.command', sect.ValueList(
types.KeyBindingName(), types.KeyBinding(),
typ.KeyBindingName(), typ.KeyBinding(),
('<Escape>', 'leave-mode'),
('<Ctrl-P>', 'command-history-prev'),
('<Ctrl-N>', 'command-history-next'),
@ -726,7 +723,7 @@ DATA = OrderedDict([
)),
('keybind.prompt', sect.ValueList(
types.KeyBindingName(), types.KeyBinding(),
typ.KeyBindingName(), typ.KeyBinding(),
('<Escape>', 'leave-mode'),
('<Return>', 'prompt-accept'),
('y', 'prompt-yes'),
@ -749,255 +746,255 @@ DATA = OrderedDict([
)),
('aliases', sect.ValueList(
types.String(forbidden=' '), types.Command(),
typ.String(forbidden=' '), typ.Command(),
)),
('colors', sect.KeyValue(
('completion.fg',
SettingValue(types.QtColor(), 'white'),
SettingValue(typ.QtColor(), 'white'),
"Text color of the completion widget."),
('completion.bg',
SettingValue(types.QssColor(), '#333333'),
SettingValue(typ.QssColor(), '#333333'),
"Background color of the completion widget."),
('completion.item.bg',
SettingValue(types.QssColor(), '${completion.bg}'),
SettingValue(typ.QssColor(), '${completion.bg}'),
"Background color of completion widget items."),
('completion.category.fg',
SettingValue(types.QtColor(), 'white'),
SettingValue(typ.QtColor(), 'white'),
"Foreground color of completion widget category headers."),
('completion.category.bg',
SettingValue(types.QssColor(), 'qlineargradient(x1:0, y1:0, x2:0, '
SettingValue(typ.QssColor(), 'qlineargradient(x1:0, y1:0, x2:0, '
'y2:1, stop:0 #888888, stop:1 #505050)'),
"Background color of the completion widget category headers."),
('completion.category.border.top',
SettingValue(types.QssColor(), 'black'),
SettingValue(typ.QssColor(), 'black'),
"Top border color of the completion widget category headers."),
('completion.category.border.bottom',
SettingValue(types.QssColor(), '${completion.category.border.top}'),
SettingValue(typ.QssColor(), '${completion.category.border.top}'),
"Bottom border color of the completion widget category headers."),
('completion.item.selected.fg',
SettingValue(types.QtColor(), 'black'),
SettingValue(typ.QtColor(), 'black'),
"Foreground color of the selected completion item."),
('completion.item.selected.bg',
SettingValue(types.QssColor(), '#e8c000'),
SettingValue(typ.QssColor(), '#e8c000'),
"Background color of the selected completion item."),
('completion.item.selected.border.top',
SettingValue(types.QssColor(), '#bbbb00'),
SettingValue(typ.QssColor(), '#bbbb00'),
"Top border color of the completion widget category headers."),
('completion.item.selected.border.bottom',
SettingValue(types.QssColor(), '${completion.item.selected.border.'
SettingValue(typ.QssColor(), '${completion.item.selected.border.'
'top}'),
"Bottom border color of the selected completion item."),
('completion.match.fg',
SettingValue(types.QssColor(), '#ff4444'),
SettingValue(typ.QssColor(), '#ff4444'),
"Foreground color of the matched text in the completion."),
('statusbar.bg',
SettingValue(types.QssColor(), 'black'),
SettingValue(typ.QssColor(), 'black'),
"Foreground color of the statusbar."),
('statusbar.fg',
SettingValue(types.QssColor(), 'white'),
SettingValue(typ.QssColor(), 'white'),
"Foreground color of the statusbar."),
('statusbar.bg.error',
SettingValue(types.QssColor(), 'red'),
SettingValue(typ.QssColor(), 'red'),
"Background color of the statusbar if there was an error."),
('statusbar.bg.prompt',
SettingValue(types.QssColor(), 'darkblue'),
SettingValue(typ.QssColor(), 'darkblue'),
"Background color of the statusbar if there is a prompt."),
('statusbar.bg.insert',
SettingValue(types.QssColor(), 'darkgreen'),
SettingValue(typ.QssColor(), 'darkgreen'),
"Background color of the statusbar in insert mode."),
('statusbar.progress.bg',
SettingValue(types.QssColor(), 'white'),
SettingValue(typ.QssColor(), 'white'),
"Background color of the progress bar."),
('statusbar.url.fg',
SettingValue(types.QssColor(), '${statusbar.fg}'),
SettingValue(typ.QssColor(), '${statusbar.fg}'),
"Default foreground color of the URL in the statusbar."),
('statusbar.url.fg.success',
SettingValue(types.QssColor(), 'lime'),
SettingValue(typ.QssColor(), 'lime'),
"Foreground color of the URL in the statusbar on successful "
"load."),
('statusbar.url.fg.error',
SettingValue(types.QssColor(), 'orange'),
SettingValue(typ.QssColor(), 'orange'),
"Foreground color of the URL in the statusbar on error."),
('statusbar.url.fg.warn',
SettingValue(types.QssColor(), 'yellow'),
SettingValue(typ.QssColor(), 'yellow'),
"Foreground color of the URL in the statusbar when there's a "
"warning."),
('statusbar.url.fg.hover',
SettingValue(types.QssColor(), 'aqua'),
"Foreground color of the URL in the statusbar for hovered "
"links."),
SettingValue(typ.QssColor(), 'aqua'),
"Foreground color of the URL in the statusbar for hovered links."),
('tab.fg',
SettingValue(types.QtColor(), 'white'),
SettingValue(typ.QtColor(), 'white'),
"Foreground color of tabs."),
('tab.bg.odd',
SettingValue(types.QtColor(), 'grey'),
SettingValue(typ.QtColor(), 'grey'),
"Background color of unselected odd tabs."),
('tab.bg.even',
SettingValue(types.QtColor(), 'darkgrey'),
SettingValue(typ.QtColor(), 'darkgrey'),
"Background color of unselected even tabs."),
('tab.bg.selected',
SettingValue(types.QtColor(), 'black'),
SettingValue(typ.QtColor(), 'black'),
"Background color of selected tabs."),
('tab.bg.bar',
SettingValue(types.QtColor(), '#555555'),
SettingValue(typ.QtColor(), '#555555'),
"Background color of the tabbar."),
('tab.indicator.start',
SettingValue(types.QtColor(), '#0000aa'),
SettingValue(typ.QtColor(), '#0000aa'),
"Color gradient start for the tab indicator."),
('tab.indicator.stop',
SettingValue(types.QtColor(), '#00aa00'),
SettingValue(typ.QtColor(), '#00aa00'),
"Color gradient end for the tab indicator."),
('tab.indicator.error',
SettingValue(types.QtColor(), '#ff0000'),
SettingValue(typ.QtColor(), '#ff0000'),
"Color for the tab indicator on errors.."),
('tab.indicator.system',
SettingValue(types.ColorSystem(), 'rgb'),
SettingValue(typ.ColorSystem(), 'rgb'),
"Color gradient interpolation system for the tab indicator."),
('tab.seperator',
SettingValue(types.QssColor(), '#555555'),
SettingValue(typ.QssColor(), '#555555'),
"Color for the tab seperator."),
('hints.fg',
SettingValue(types.CssColor(), 'black'),
SettingValue(typ.CssColor(), 'black'),
"Font color for hints."),
('hints.fg.match',
SettingValue(types.CssColor(), 'green'),
SettingValue(typ.CssColor(), 'green'),
"Font color for the matched part of hints."),
('hints.bg',
SettingValue(types.CssColor(), '-webkit-gradient(linear, left top, '
'left bottom, color-stop(0%,#FFF785), '
'color-stop(100%,#FFC542))'),
SettingValue(typ.CssColor(), '-webkit-gradient(linear, left top, '
'left bottom, color-stop(0%,#FFF785), '
'color-stop(100%,#FFC542))'),
"Background color for hints."),
('downloads.fg',
SettingValue(types.QtColor(), '#ffffff'),
SettingValue(typ.QtColor(), '#ffffff'),
"Foreground color for downloads."),
('downloads.bg.bar',
SettingValue(types.QssColor(), 'black'),
SettingValue(typ.QssColor(), 'black'),
"Background color for the download bar."),
('downloads.bg.start',
SettingValue(types.QtColor(), '#0000aa'),
SettingValue(typ.QtColor(), '#0000aa'),
"Color gradient start for downloads."),
('downloads.bg.stop',
SettingValue(types.QtColor(), '#00aa00'),
SettingValue(typ.QtColor(), '#00aa00'),
"Color gradient end for downloads."),
('downloads.bg.system',
SettingValue(types.ColorSystem(), 'rgb'),
SettingValue(typ.ColorSystem(), 'rgb'),
"Color gradient interpolation system for downloads."),
)),
('fonts', sect.KeyValue(
('_monospace',
SettingValue(types.Font(), 'Terminus, Monospace, "DejaVu Sans Mono", '
SettingValue(typ.Font(), 'Terminus, Monospace, "DejaVu Sans Mono", '
'Consolas, Monaco, "Bitstream Vera Sans Mono", '
'"Andale Mono", "Liberation Mono", "Courier New", '
'Courier, monospace, Fixed, Terminal'),
"Default monospace fonts."),
('completion',
SettingValue(types.Font(), '8pt ${_monospace}'),
SettingValue(typ.Font(), '8pt ${_monospace}'),
"Font used in the completion widget."),
('tabbar',
SettingValue(types.QtFont(), '8pt ${_monospace}'),
SettingValue(typ.QtFont(), '8pt ${_monospace}'),
"Font used in the tabbar."),
('statusbar',
SettingValue(types.Font(), '8pt ${_monospace}'),
SettingValue(typ.Font(), '8pt ${_monospace}'),
"Font used in the statusbar."),
('downloads',
SettingValue(types.Font(), '8pt ${_monospace}'),
SettingValue(typ.Font(), '8pt ${_monospace}'),
"Font used for the downloadbar."),
('hints',
SettingValue(types.Font(), 'bold 12px Monospace'),
SettingValue(typ.Font(), 'bold 12px Monospace'),
"Font used for the hints."),
('debug-console',
SettingValue(types.QtFont(), '8pt ${_monospace}'),
SettingValue(typ.QtFont(), '8pt ${_monospace}'),
"Font used for the debugging console."),
('web-family-standard',
SettingValue(types.String(none_ok=True), ''),
SettingValue(typ.String(none_ok=True), ''),
"Font family for standard fonts."),
('web-family-fixed',
SettingValue(types.String(none_ok=True), ''),
SettingValue(typ.String(none_ok=True), ''),
"Font family for fixed fonts."),
('web-family-serif',
SettingValue(types.String(none_ok=True), ''),
SettingValue(typ.String(none_ok=True), ''),
"Font family for serif fonts."),
('web-family-sans-serif',
SettingValue(types.String(none_ok=True), ''),
SettingValue(typ.String(none_ok=True), ''),
"Font family for sans-serif fonts."),
('web-family-cursive',
SettingValue(types.String(none_ok=True), ''),
SettingValue(typ.String(none_ok=True), ''),
"Font family for cursive fonts."),
('web-family-fantasy',
SettingValue(types.String(none_ok=True), ''),
SettingValue(typ.String(none_ok=True), ''),
"Font family for fantasy fonts."),
('web-size-minimum',
SettingValue(types.Int(none_ok=True, minval=1, maxval=MAXVALS['int']),
''),
SettingValue(
typ.Int(none_ok=True, minval=1, maxval=MAXVALS['int']), ''),
"The hard minimum font size."),
('web-size-minimum-logical',
SettingValue(types.Int(none_ok=True, minval=1, maxval=MAXVALS['int']),
''),
SettingValue(
typ.Int(none_ok=True, minval=1, maxval=MAXVALS['int']), ''),
"The minimum logical font size that is applied when zooming out."),
('web-size-default',
SettingValue(types.Int(none_ok=True, minval=1, maxval=MAXVALS['int']),
''), "The default font size for regular text."),
SettingValue(
typ.Int(none_ok=True, minval=1, maxval=MAXVALS['int']), ''),
"The default font size for regular text."),
('web-size-default-fixed',
SettingValue(types.Int(none_ok=True, minval=1, maxval=MAXVALS['int']),
''),
SettingValue(
typ.Int(none_ok=True, minval=1, maxval=MAXVALS['int']), ''),
"The default font size for fixed-pitch text."),
)),
])

View File

@ -23,13 +23,13 @@ import re
import shlex
import codecs
import os.path
from sre_constants import error as RegexError
import sre_constants
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QColor, QFont
from PyQt5.QtNetwork import QNetworkProxy
import qutebrowser.commands.utils as cmdutils
from qutebrowser.commands import utils as cmdutils
SYSTEM_PROXY = object() # Return value for Proxy type
@ -734,7 +734,7 @@ class Regex(BaseType):
raise ValidationError(value, "may not be empty!")
try:
re.compile(value, self.flags)
except RegexError as e:
except sre_constants.error as e:
raise ValidationError(value, "must be a valid regex - " + str(e))
def transform(self, value):
@ -762,7 +762,7 @@ class RegexList(List):
def validate(self, value):
try:
vals = self.transform(value)
except RegexError as e:
except sre_constants.error as e:
raise ValidationError(value, "must be a list valid regexes - " +
str(e))
if not self.none_ok and None in vals:

View File

@ -21,12 +21,12 @@
import os
import os.path
from configparser import ConfigParser
import configparser
import qutebrowser.utils.log as log
from qutebrowser.utils import log
class ReadConfigParser(ConfigParser):
class ReadConfigParser(configparser.ConfigParser):
"""Our own ConfigParser subclass to read the main config.

View File

@ -24,7 +24,7 @@ import os.path
from PyQt5.QtCore import pyqtSlot
import qutebrowser.utils.log as log
from qutebrowser.utils import log
class LineConfigParser:
@ -82,7 +82,7 @@ class LineConfigParser:
log.destroy.debug("No data to save.")
return
# We need to import this here because config needs LineConfigParser.
import qutebrowser.config.config as config
from qutebrowser.config import config
limit = -1 if self._limit is None else config.get(*self._limit)
if limit == 0:
return
@ -98,7 +98,7 @@ class LineConfigParser:
if self._limit is None:
return
# We need to import this here because config needs LineConfigParser.
import qutebrowser.config.config as config
from qutebrowser.config import config
value = config.get(section, option)
if (section, option) == self._limit and value == 0:
if os.path.exists(self._configfile):

View File

@ -19,9 +19,9 @@
"""Setting sections used for qutebrowser."""
from collections import OrderedDict, ChainMap
import collections
from qutebrowser.config.value import SettingValue
from qutebrowser.config import value as confvalue
class Section:
@ -108,7 +108,7 @@ class KeyValue(Section):
super().__init__()
if not defaults:
return
self.values = OrderedDict()
self.values = collections.OrderedDict()
for (k, v, desc) in defaults:
assert k not in self.values, k
self.values[k] = v
@ -160,17 +160,17 @@ class ValueList(Section):
self._ordered_value_cache = None
self.keytype = keytype
self.valtype = valtype
self.layers = OrderedDict([
('default', OrderedDict()),
('conf', OrderedDict()),
('temp', OrderedDict()),
self.layers = collections.OrderedDict([
('default', collections.OrderedDict()),
('conf', collections.OrderedDict()),
('temp', collections.OrderedDict()),
])
defaultlayer = self.layers['default']
for key, value in defaults:
assert key not in defaultlayer, key
defaultlayer[key] = SettingValue(valtype, value)
self.values = ChainMap(self.layers['temp'], self.layers['conf'],
self.layers['default'])
defaultlayer[key] = confvalue.SettingValue(valtype, value)
self.values = collections.ChainMap(
self.layers['temp'], self.layers['conf'], self.layers['default'])
@property
def ordered_values(self):
@ -180,7 +180,7 @@ class ValueList(Section):
iterating/items/etc. when order matters.
"""
if self._ordered_value_cache is None:
self._ordered_value_cache = OrderedDict()
self._ordered_value_cache = collections.OrderedDict()
for layer in self.layers.values():
self._ordered_value_cache.update(layer)
return self._ordered_value_cache
@ -190,14 +190,15 @@ class ValueList(Section):
if key in self.layers[layer]:
self.layers[layer][key].setv(layer, value, interpolated)
else:
val = SettingValue(self.valtype)
val = confvalue.SettingValue(self.valtype)
val.setv(layer, value, interpolated)
self.layers[layer][key] = val
self._ordered_value_cache = None
def dump_userconfig(self):
changed = []
mapping = ChainMap(self.layers['temp'], self.layers['conf'])
mapping = collections.ChainMap(
self.layers['temp'], self.layers['conf'])
for k, v in mapping.items():
try:
if v.value != self.layers['default'][k].value:

View File

@ -24,13 +24,13 @@ Module attributes:
_fontdict: The global cached FontDict.
"""
from functools import partial
import functools
from PyQt5.QtGui import QColor
import qutebrowser.config.config as config
from qutebrowser.config import config
from qutebrowser.utils import misc as utils
from qutebrowser.utils.log import style as logger
from qutebrowser.utils.misc import compact_text
_colordict = None
@ -68,9 +68,10 @@ def set_register_stylesheet(obj):
"""
qss = get_stylesheet(obj.STYLESHEET)
logger.debug("stylesheet for {}: {}".format(obj.__class__.__name__,
compact_text(qss)))
utils.compact_text(qss)))
obj.setStyleSheet(qss)
config.instance().changed.connect(partial(_update_stylesheet, obj))
config.instance().changed.connect(
functools.partial(_update_stylesheet, obj))
def _update_stylesheet(obj, _section, _option):

View File

@ -19,7 +19,7 @@
"""A single value (with multiple layers possibly) in the config."""
from collections import OrderedDict
import collections
class SettingValue:
@ -43,7 +43,8 @@ class SettingValue:
default: Raw value to set.
"""
self.typ = typ
self._values = OrderedDict.fromkeys(['temp', 'conf', 'default'])
self._values = collections.OrderedDict.fromkeys(
['temp', 'conf', 'default'])
self._values['default'] = default
def __str__(self):
@ -72,7 +73,7 @@ class SettingValue:
startlayer: The first layer to include.
"""
idx = list(self._values.keys()).index(startlayer)
d = OrderedDict(list(self._values.items())[idx:])
d = collections.OrderedDict(list(self._values.items())[idx:])
return d
def get_first_value(self, startlayer=None):

View File

@ -30,11 +30,11 @@ from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWebKit import QWebSettings
from PyQt5.QtCore import QStandardPaths
import qutebrowser.config.config as config
from qutebrowser.utils.usertypes import enum
from qutebrowser.utils.misc import get_standard_dir
from qutebrowser.config import config
from qutebrowser.utils import usertypes
from qutebrowser.utils import misc as utils
MapType = enum('MapType', 'attribute', 'setter', 'static_setter')
MapType = usertypes.enum('MapType', 'attribute', 'setter', 'static_setter')
MAPPINGS = {
@ -177,7 +177,7 @@ def _set_setting(typ, arg, value):
def init():
"""Initialize the global QWebSettings."""
global settings
cachedir = get_standard_dir(QStandardPaths.CacheLocation)
cachedir = utils.get_standard_dir(QStandardPaths.CacheLocation)
QWebSettings.enablePersistentStorage(cachedir)
settings = QWebSettings.globalSettings()
for sectname, section in MAPPINGS.items():

View File

@ -21,14 +21,14 @@
import re
import string
from functools import partial
import functools
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QObject
import qutebrowser.config.config as config
from qutebrowser.utils.usertypes import enum, Timer
from qutebrowser.config import config
from qutebrowser.utils import usertypes
from qutebrowser.utils import misc as utils
from qutebrowser.utils.log import keyboard as logger
from qutebrowser.utils.misc import keyevent_to_string, normalize_keystr
class BaseKeyParser(QObject):
@ -71,8 +71,9 @@ class BaseKeyParser(QObject):
keystring_updated = pyqtSignal(str)
do_log = True
Match = enum('Match', 'partial', 'definitive', 'ambiguous', 'none')
Type = enum('Type', 'chain', 'special')
Match = usertypes.enum('Match', 'partial', 'definitive', 'ambiguous',
'none')
Type = usertypes.enum('Type', 'chain', 'special')
def __init__(self, parent=None, supports_count=None,
supports_chains=False):
@ -113,7 +114,7 @@ class BaseKeyParser(QObject):
Return:
True if event has been handled, False otherwise.
"""
binding = keyevent_to_string(e)
binding = utils.keyevent_to_string(e)
if binding is None:
self._debug_log("Ignoring only-modifier keyeevent.")
return False
@ -266,11 +267,11 @@ class BaseKeyParser(QObject):
# execute in `time' ms
self._debug_log("Scheduling execution of {} in {}ms".format(
binding, time))
self._timer = Timer(self, 'ambigious_match')
self._timer = usertypes.Timer(self, 'ambigious_match')
self._timer.setSingleShot(True)
self._timer.setInterval(time)
self._timer.timeout.connect(partial(self.delayed_exec, binding,
count))
self._timer.timeout.connect(
functools.partial(self.delayed_exec, binding, count))
self._timer.start()
def delayed_exec(self, command, count):
@ -329,7 +330,7 @@ class BaseKeyParser(QObject):
if not cmd:
continue
elif key.startswith('<') and key.endswith('>'):
keystr = normalize_keystr(key[1:-1])
keystr = utils.normalize_keystr(key[1:-1])
self.special_bindings[keystr] = cmd
elif self._supports_chains:
self.bindings[key] = cmd

View File

@ -20,10 +20,9 @@
"""Advanced keyparsers."""
from qutebrowser.keyinput.basekeyparser import BaseKeyParser
import qutebrowser.utils.message as message
from qutebrowser.commands.runners import CommandRunner
from qutebrowser.commands.exceptions import CommandMetaError, CommandError
from qutebrowser.utils import message
from qutebrowser.commands import runners
from qutebrowser.commands import exceptions as cmdexc
class CommandKeyParser(BaseKeyParser):
@ -37,12 +36,12 @@ class CommandKeyParser(BaseKeyParser):
def __init__(self, parent=None, supports_count=None,
supports_chains=False):
super().__init__(parent, supports_count, supports_chains)
self.commandrunner = CommandRunner()
self.commandrunner = runners.CommandRunner()
def execute(self, cmdstr, _keytype, count=None):
try:
self.commandrunner.run(cmdstr, count)
except (CommandMetaError, CommandError) as e:
except (cmdexc.CommandMetaError, cmdexc.CommandError) as e:
message.error(e, immediately=True)

View File

@ -27,11 +27,11 @@ from PyQt5.QtGui import QWindow
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QEvent
from PyQt5.QtWidgets import QApplication
import qutebrowser.config.config as config
import qutebrowser.commands.utils as cmdutils
from qutebrowser.config import config
from qutebrowser.commands import utils as cmdutils
from qutebrowser.commands import exceptions as cmdexc
from qutebrowser.utils import usertypes
from qutebrowser.utils.log import modes as logger
from qutebrowser.utils.usertypes import KeyMode
from qutebrowser.commands.exceptions import CommandError
class ModeLockedError(Exception):
@ -96,8 +96,8 @@ class ModeManager(QObject):
arg: The mode which has been left.
"""
entered = pyqtSignal(KeyMode)
left = pyqtSignal(KeyMode)
entered = pyqtSignal(usertypes.KeyMode)
left = pyqtSignal(usertypes.KeyMode)
def __init__(self, parent=None):
super().__init__(parent)
@ -142,7 +142,7 @@ class ModeManager(QObject):
True if event should be filtered, False otherwise.
"""
handler = self._handlers[self.mode]
if self.mode != KeyMode.insert:
if self.mode != usertypes.KeyMode.insert:
logger.debug("got keypress in mode {} - calling handler {}".format(
self.mode, handler.__qualname__))
handled = handler(event) if handler is not None else False
@ -161,7 +161,7 @@ class ModeManager(QObject):
if not filter_this:
self._releaseevents_to_pass.append(event)
if self.mode != KeyMode.insert:
if self.mode != usertypes.KeyMode.insert:
logger.debug("handled: {}, forward-unbound-keys: {}, passthrough: "
"{}, is_non_alnum: {} --> filter: {}".format(
handled, self._forward_unbound_keys,
@ -186,7 +186,7 @@ class ModeManager(QObject):
filter_this = False
else:
filter_this = True
if self.mode != KeyMode.insert:
if self.mode != usertypes.KeyMode.insert:
logger.debug("filter: {}".format(filter_this))
return filter_this
@ -199,7 +199,7 @@ class ModeManager(QObject):
passthrough: Whether to pass keybindings in this mode through to
the widgets.
"""
if not isinstance(mode, KeyMode):
if not isinstance(mode, usertypes.KeyMode):
raise TypeError("Mode {} is no KeyMode member!".format(mode))
self._handlers[mode] = handler
if passthrough:
@ -215,7 +215,7 @@ class ModeManager(QObject):
Emit:
entered: With the new mode name.
"""
if not isinstance(mode, KeyMode):
if not isinstance(mode, usertypes.KeyMode):
raise TypeError("Mode {} is no KeyMode member!".format(mode))
if self.locked:
logger.debug("Not entering mode {} because mode is locked to "
@ -241,9 +241,9 @@ class ModeManager(QObject):
mode: The mode to enter.
"""
try:
m = KeyMode[mode]
m = usertypes.KeyMode[mode]
except KeyError:
raise CommandError("Mode {} does not exist!".format(mode))
raise cmdexc.CommandError("Mode {} does not exist!".format(mode))
self.enter(m, 'command')
def leave(self, mode, reason=None):
@ -267,10 +267,10 @@ class ModeManager(QObject):
self.left.emit(mode)
@cmdutils.register(instance='modeman', name='leave-mode',
not_modes=[KeyMode.normal], hide=True)
not_modes=[usertypes.KeyMode.normal], hide=True)
def leave_current_mode(self):
"""Leave the mode we're currently in."""
if self.mode == KeyMode.normal:
if self.mode == usertypes.KeyMode.normal:
raise ValueError("Can't leave normal mode!")
self.leave(self.mode, 'leave current')

View File

@ -25,18 +25,18 @@ Module attributes:
from PyQt5.QtCore import pyqtSignal, Qt
import qutebrowser.utils.message as message
import qutebrowser.config.config as config
from qutebrowser.keyinput.keyparser import CommandKeyParser
from qutebrowser.utils.usertypes import enum
from qutebrowser.utils import message
from qutebrowser.config import config
from qutebrowser.keyinput import keyparser
from qutebrowser.utils import usertypes
from qutebrowser.utils.log import keyboard as logger
STARTCHARS = ":/?"
LastPress = enum('LastPress', 'none', 'filtertext', 'keystring')
LastPress = usertypes.enum('LastPress', 'none', 'filtertext', 'keystring')
class NormalKeyParser(CommandKeyParser):
class NormalKeyParser(keyparser.CommandKeyParser):
"""KeyParser for normalmode with added STARTCHARS detection."""
@ -63,7 +63,7 @@ class NormalKeyParser(CommandKeyParser):
return super()._handle_single_key(e)
class PromptKeyParser(CommandKeyParser):
class PromptKeyParser(keyparser.CommandKeyParser):
"""KeyParser for yes/no prompts."""
@ -77,7 +77,7 @@ class PromptKeyParser(CommandKeyParser):
return '<{}>'.format(self.__class__.__name__)
class HintKeyParser(CommandKeyParser):
class HintKeyParser(keyparser.CommandKeyParser):
"""KeyChainParser for hints.

View File

@ -26,11 +26,11 @@ Module attributes:
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from qutebrowser.utils.usertypes import enum
from qutebrowser.utils.qt import qt_ensure_valid
from qutebrowser.utils import usertypes
from qutebrowser.utils import qt as qtutils
Role = enum('Role', 'marks', 'sort', start=Qt.UserRole, is_int=True)
Role = usertypes.enum('Role', 'marks', 'sort', start=Qt.UserRole, is_int=True)
class BaseCompletionModel(QStandardItemModel):
@ -74,7 +74,7 @@ class BaseCompletionModel(QStandardItemModel):
index: A QModelIndex of the item to mark.
needle: The string to mark.
"""
qt_ensure_valid(index)
qtutils.qt_ensure_valid(index)
haystack = self.data(index)
marks = self._get_marks(needle, haystack)
ok = self.setData(index, marks, Role.marks)
@ -132,7 +132,7 @@ class BaseCompletionModel(QStandardItemModel):
Return:
The item flags, or Qt.NoItemFlags on error.
"""
qt_ensure_valid(index)
qtutils.qt_ensure_valid(index)
if index.parent().isValid():
# item
return Qt.ItemIsEnabled | Qt.ItemIsSelectable

View File

@ -21,7 +21,7 @@
from PyQt5.QtCore import pyqtSlot
from qutebrowser.utils.usertypes import NeighborList
from qutebrowser.utils import usertypes
from qutebrowser.utils.log import misc as logger
@ -85,7 +85,7 @@ class History:
items = self.history
if not items:
raise HistoryEmptyError
self._tmphist = NeighborList(items)
self._tmphist = usertypes.NeighborList(items)
return self._tmphist.lastitem()
@pyqtSlot()

View File

@ -21,15 +21,14 @@
from PyQt5.QtCore import pyqtSlot, Qt, QCoreApplication
import qutebrowser.config.config as config
import qutebrowser.config.configdata as configdata
from qutebrowser.models.basecompletion import BaseCompletionModel
from qutebrowser.commands.utils import cmd_dict
from qutebrowser.config import config, configdata
from qutebrowser.models import basecompletion
from qutebrowser.commands import utils as cmdutils
from qutebrowser.utils import qt as qtutils
from qutebrowser.utils.log import completion as logger
from qutebrowser.utils.qt import qt_ensure_valid
class SettingSectionCompletionModel(BaseCompletionModel):
class SettingSectionCompletionModel(basecompletion.BaseCompletionModel):
"""A CompletionModel filled with settings sections."""
@ -43,7 +42,7 @@ class SettingSectionCompletionModel(BaseCompletionModel):
self.new_item(cat, name, desc)
class SettingOptionCompletionModel(BaseCompletionModel):
class SettingOptionCompletionModel(basecompletion.BaseCompletionModel):
"""A CompletionModel filled with settings and their descriptions.
@ -88,14 +87,14 @@ class SettingOptionCompletionModel(BaseCompletionModel):
return
val = config.get(section, option, raw=True)
idx = item.index()
qt_ensure_valid(idx)
qtutils.qt_ensure_valid(idx)
ok = self.setData(idx, val, Qt.DisplayRole)
if not ok:
raise ValueError("Setting data failed! (section: {}, option: {}, "
"value: {})".format(section, option, val))
class SettingValueCompletionModel(BaseCompletionModel):
class SettingValueCompletionModel(basecompletion.BaseCompletionModel):
"""A CompletionModel filled with setting values.
@ -139,14 +138,14 @@ class SettingValueCompletionModel(BaseCompletionModel):
if not value:
value = '""'
idx = self.cur_item.index()
qt_ensure_valid(idx)
qtutils.qt_ensure_valid(idx)
ok = self.setData(idx, value, Qt.DisplayRole)
if not ok:
raise ValueError("Setting data failed! (section: {}, option: {}, "
"value: {})".format(section, option, value))
class CommandCompletionModel(BaseCompletionModel):
class CommandCompletionModel(basecompletion.BaseCompletionModel):
"""A CompletionModel filled with all commands and descriptions."""
@ -154,9 +153,9 @@ class CommandCompletionModel(BaseCompletionModel):
def __init__(self, parent=None):
super().__init__(parent)
assert cmd_dict
assert cmdutils.cmd_dict
cmdlist = []
for obj in set(cmd_dict.values()):
for obj in set(cmdutils.cmd_dict.values()):
if obj.hide or (obj.debug and not
QCoreApplication.instance().args.debug):
pass

View File

@ -25,9 +25,9 @@ Contains:
from PyQt5.QtCore import QSortFilterProxyModel, QModelIndex
from qutebrowser.models.basecompletion import Role
from qutebrowser.models import basecompletion as completion
from qutebrowser.utils import qt as qtutils
from qutebrowser.utils.log import completion as logger
from qutebrowser.utils.qt import qt_ensure_valid
class CompletionFilterModel(QSortFilterProxyModel):
@ -81,7 +81,7 @@ class CompletionFilterModel(QSortFilterProxyModel):
count = 0
for i in range(self.rowCount()):
cat = self.index(i, 0)
qt_ensure_valid(cat)
qtutils.qt_ensure_valid(cat)
count += self.rowCount(cat)
return count
@ -89,10 +89,10 @@ class CompletionFilterModel(QSortFilterProxyModel):
"""Return the first item in the model."""
for i in range(self.rowCount()):
cat = self.index(i, 0)
qt_ensure_valid(cat)
qtutils.qt_ensure_valid(cat)
if cat.model().hasChildren(cat):
index = self.index(0, 0, cat)
qt_ensure_valid(index)
qtutils.qt_ensure_valid(index)
return index
return QModelIndex()
@ -100,10 +100,10 @@ class CompletionFilterModel(QSortFilterProxyModel):
"""Return the last item in the model."""
for i in range(self.rowCount() - 1, -1, -1):
cat = self.index(i, 0)
qt_ensure_valid(cat)
qtutils.qt_ensure_valid(cat)
if cat.model().hasChildren(cat):
index = self.index(self.rowCount(cat) - 1, 0, cat)
qt_ensure_valid(index)
qtutils.qt_ensure_valid(index)
return index
return QModelIndex()
@ -111,12 +111,12 @@ class CompletionFilterModel(QSortFilterProxyModel):
"""Mark the given text in all visible items."""
for i in range(self.rowCount()):
cat = self.index(i, 0)
qt_ensure_valid(cat)
qtutils.qt_ensure_valid(cat)
for k in range(self.rowCount(cat)):
index = self.index(k, 0, cat)
qt_ensure_valid(index)
qtutils.qt_ensure_valid(index)
index = self.mapToSource(index)
qt_ensure_valid(index)
qtutils.qt_ensure_valid(index)
self.srcmodel.mark_item(index, text)
def setSourceModel(self, model):
@ -142,7 +142,7 @@ class CompletionFilterModel(QSortFilterProxyModel):
if parent == QModelIndex():
return True
idx = self.srcmodel.index(row, 0, parent)
qt_ensure_valid(idx)
qtutils.qt_ensure_valid(idx)
data = self.srcmodel.data(idx)
# TODO more sophisticated filtering
if not self.pattern:
@ -162,11 +162,11 @@ class CompletionFilterModel(QSortFilterProxyModel):
Return:
True if left < right, else False
"""
qt_ensure_valid(lindex)
qt_ensure_valid(rindex)
qtutils.qt_ensure_valid(lindex)
qtutils.qt_ensure_valid(rindex)
left_sort = self.srcmodel.data(lindex, role=Role.sort)
right_sort = self.srcmodel.data(rindex, role=Role.sort)
left_sort = self.srcmodel.data(lindex, role=completion.Role.sort)
right_sort = self.srcmodel.data(rindex, role=completion.Role.sort)
if left_sort is not None and right_sort is not None:
return left_sort < right_sort

View File

@ -23,12 +23,12 @@ from PyQt5.QtCore import (pyqtSlot, Qt, QVariant, QAbstractListModel,
QModelIndex)
from PyQt5.QtWidgets import QApplication
import qutebrowser.config.config as config
from qutebrowser.utils.usertypes import enum
from qutebrowser.utils.qt import qt_ensure_valid
from qutebrowser.config import config
from qutebrowser.utils import usertypes
from qutebrowser.utils import qt as qtutils
Role = enum('Role', 'item', start=Qt.UserRole, is_int=True)
Role = usertypes.enum('Role', 'item', start=Qt.UserRole, is_int=True)
class DownloadModel(QAbstractListModel):
@ -57,7 +57,7 @@ class DownloadModel(QAbstractListModel):
def on_data_changed(self, idx):
"""Update view when DownloadManager data changed."""
model_idx = self.index(idx, 0)
qt_ensure_valid(model_idx)
qtutils.qt_ensure_valid(model_idx)
self.dataChanged.emit(model_idx, model_idx)
def last_index(self):
@ -79,7 +79,7 @@ class DownloadModel(QAbstractListModel):
def data(self, index, role):
"""Download data from DownloadManager."""
qt_ensure_valid(index)
qtutils.qt_ensure_valid(index)
if index.parent().isValid() or index.column() != 0:
return QVariant()

View File

@ -29,12 +29,9 @@ except ImportError:
else:
SSL_AVAILABLE = QSslSocket.supportsSsl()
import qutebrowser.config.config as config
import qutebrowser.utils.message as message
import qutebrowser.utils.log as log
from qutebrowser.network.qutescheme import QuteSchemeHandler
from qutebrowser.network.schemehandler import ErrorNetworkReply
from qutebrowser.utils.usertypes import PromptMode
from qutebrowser.config import config
from qutebrowser.utils import message, log, usertypes
from qutebrowser.network import qutescheme, schemehandler
class NetworkManager(QNetworkAccessManager):
@ -52,7 +49,7 @@ class NetworkManager(QNetworkAccessManager):
super().__init__(parent)
self._requests = []
self._scheme_handlers = {
'qute': QuteSchemeHandler(),
'qute': qutescheme.QuteSchemeHandler(),
}
cookiejar = QCoreApplication.instance().cookiejar
parent = cookiejar.parent()
@ -105,14 +102,14 @@ class NetworkManager(QNetworkAccessManager):
def on_authentication_required(self, _reply, authenticator):
"""Called when a website needs authentication."""
answer = message.ask("Username ({}):".format(authenticator.realm()),
mode=PromptMode.user_pwd)
mode=usertypes.PromptMode.user_pwd)
self._fill_authenticator(authenticator, answer)
@pyqtSlot('QNetworkProxy', 'QAuthenticator')
def on_proxy_authentication_required(self, _proxy, authenticator):
"""Called when a proxy needs authentication."""
answer = message.ask("Proxy username ({}):".format(
authenticator.realm()), mode=PromptMode.user_pwd)
authenticator.realm()), mode=usertypes.PromptMode.user_pwd)
self._fill_authenticator(authenticator, answer)
def createRequest(self, op, req, outgoing_data):
@ -131,7 +128,7 @@ class NetworkManager(QNetworkAccessManager):
"""
scheme = req.url().scheme()
if scheme == 'https' and not SSL_AVAILABLE:
return ErrorNetworkReply(
return schemehandler.ErrorNetworkReply(
req, "SSL is not supported by the installed Qt library!",
QNetworkReply.ProtocolUnknownError)
elif scheme in self._scheme_handlers:

View File

@ -19,11 +19,11 @@
"""Handling of proxies."""
import qutebrowser.config.config as config
from qutebrowser.config.conftypes import SYSTEM_PROXY
from PyQt5.QtNetwork import QNetworkProxyFactory
from qutebrowser.config import config, conftypes
def init():
"""Set the application wide proxy factory."""
@ -44,7 +44,7 @@ class ProxyFactory(QNetworkProxyFactory):
A list of QNetworkProxy objects in order of preference.
"""
proxy = config.get('network', 'proxy')
if proxy is SYSTEM_PROXY:
if proxy is conftypes.SYSTEM_PROXY:
return QNetworkProxyFactory.systemProxyForQuery(query)
else:
return [proxy]

View File

@ -29,12 +29,10 @@ import html as pyhtml
from PyQt5.QtNetwork import QNetworkReply
import qutebrowser
import qutebrowser.utils.log as logutils
import qutebrowser.utils.version as version
from qutebrowser.network.schemehandler import (SchemeHandler,
SpecialNetworkReply,
ErrorNetworkReply)
from qutebrowser.utils.misc import read_file
from qutebrowser.network import schemehandler
from qutebrowser.utils import version
from qutebrowser.utils import log as logutils
from qutebrowser.utils import misc as utils
_HTML_TEMPLATE = """
@ -73,7 +71,7 @@ def _get_html(title, snippet, head=None):
return html
class QuteSchemeHandler(SchemeHandler):
class QuteSchemeHandler(schemehandler.SchemeHandler):
"""Scheme handler for qute: URLs."""
@ -97,12 +95,13 @@ class QuteSchemeHandler(SchemeHandler):
except AttributeError:
errorstr = "No handler found for {}!".format(
request.url().toDisplayString())
return ErrorNetworkReply(request, errorstr,
QNetworkReply.ContentNotFoundError,
self.parent())
return schemehandler.ErrorNetworkReply(
request, errorstr, QNetworkReply.ContentNotFoundError,
self.parent())
else:
data = handler()
return SpecialNetworkReply(request, data, 'text/html', self.parent())
return schemehandler.SpecialNetworkReply(
request, data, 'text/html', self.parent())
class QuteHandlers:
@ -171,4 +170,4 @@ class QuteHandlers:
@classmethod
def gpl(cls):
"""Handler for qute:gpl. Return HTML content as bytes."""
return read_file('html/COPYING.html').encode('ASCII')
return utils.read_file('html/COPYING.html').encode('ASCII')

View File

@ -37,14 +37,14 @@ except ImportError:
sys.exit(100)
check_python_version()
from argparse import ArgumentParser
import qutebrowser.utils.earlyinit as earlyinit
import argparse
from qutebrowser.utils import earlyinit
def get_argparser():
"""Get the argparse parser."""
parser = ArgumentParser("usage: qutebrowser",
description=qutebrowser.__description__)
parser = argparse.ArgumentParser("usage: qutebrowser",
description=qutebrowser.__description__)
parser.add_argument('-c', '--confdir', help="Set config directory (empty "
"for no config storage)")
parser.add_argument('-V', '--version', help="Show version and quit.",
@ -103,7 +103,7 @@ def main():
earlyinit.check_pyqt_core()
# We do this import late as we need to do the version checking first.
# Note we may not import webkit stuff yet as fix_harfbuzz didn't run.
import qutebrowser.utils.log as log
from qutebrowser.utils import log
log.init_log(args)
log.init.debug("Log initialized.")
log.init.debug("Doing early init.")
@ -113,10 +113,10 @@ def main():
earlyinit.check_pkg_resources()
earlyinit.check_pypeg2()
# We do this import late as we need to fix harfbuzz first.
from qutebrowser.app import Application
from qutebrowser.utils.debug import trace_lines
from qutebrowser import app
from qutebrowser.utils import debug
import PyQt5.QtWidgets as QtWidgets
app = Application(args)
app = app.Application(args)
# We set qApp explicitely here to reduce the risk of segfaults while
# quitting.
# See https://bugs.launchpad.net/ubuntu/+source/python-qt4/+bug/561303/comments/7
@ -127,6 +127,6 @@ def main():
ret = app.exec_()
if args.debug_exit:
print("Now logging late shutdown.", file=sys.stderr)
trace_lines(True)
debug.trace_lines(True)
QtWidgets.qApp = None
return ret

View File

@ -19,13 +19,13 @@
"""Tests for qutebrowser.config.conftypes."""
import unittest
import unittest.mock as mock
import re
from collections import namedtuple
import collections
from unittest import mock
import qutebrowser.config.conftypes as conftypes
from qutebrowser.test.stubs import FakeCmdUtils, FakeCommand
from qutebrowser.utils.debug import qenum_key
from qutebrowser.config import conftypes
from qutebrowser.test import stubs
from qutebrowser.utils import debug
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QColor, QFont
@ -37,9 +37,10 @@ class Font(QFont):
"""A QFont with a nicer repr()."""
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(),
qenum_key(QFont, self.weight(), add_base=True, klass=QFont.Weight),
self.family(), self.pointSize(), self.pixelSize(), weight,
self.style())
@classmethod
@ -853,10 +854,10 @@ class CommandTests(unittest.TestCase):
def setUp(self):
self.old_cmdutils = conftypes.cmdutils
commands = {
'cmd1': FakeCommand("desc 1"),
'cmd2': FakeCommand("desc 2"),
'cmd1': stubs.FakeCommand("desc 1"),
'cmd2': stubs.FakeCommand("desc 2"),
}
conftypes.cmdutils = FakeCmdUtils(commands)
conftypes.cmdutils = stubs.FakeCmdUtils(commands)
self.t = conftypes.Command()
def tearDown(self):
@ -1057,7 +1058,8 @@ class QssColorTests(QtColorTests):
self.assertEqual(self.t.transform(v), v, v)
FontDesc = namedtuple('FontDesc', ['style', 'weight', 'pt', 'px', 'family'])
FontDesc = collections.namedtuple('FontDesc',
['style', 'weight', 'pt', 'px', 'family'])
class FontTests(unittest.TestCase):

View File

@ -20,13 +20,13 @@
"""Helpers needed by tests."""
import os
from contextlib import contextmanager
from unittest.mock import create_autospec
import contextlib
from unittest import mock
from PyQt5.QtGui import QKeyEvent
@contextmanager
@contextlib.contextmanager
def environ_set_temp(name, value):
"""Set a temporary environment variable."""
try:
@ -43,8 +43,8 @@ def environ_set_temp(name, value):
def fake_keyevent(key, modifiers=0, text=''):
"""Generate a new fake QKeyPressEvent."""
mock = create_autospec(QKeyEvent, instance=True)
mock.key.return_value = key
mock.modifiers.return_value = modifiers
mock.text.return_value = text
return mock
evtmock = mock.create_autospec(QKeyEvent, instance=True)
evtmock.key.return_value = key
evtmock.modifiers.return_value = modifiers
evtmock.text.return_value = text
return evtmock

View File

@ -23,14 +23,14 @@
import logging
import unittest
from unittest.mock import Mock, patch
import qutebrowser.keyinput.basekeyparser as basekeyparser
from qutebrowser.test.stubs import ConfigStub
from qutebrowser.test.helpers import fake_keyevent
from unittest import mock
from PyQt5.QtCore import Qt
from qutebrowser.keyinput import basekeyparser
from qutebrowser.test import stubs, helpers
CONFIG = {'test': {'<Ctrl-a>': 'ctrla',
'a': 'a',
'ba': 'ba',
@ -42,7 +42,7 @@ CONFIG = {'test': {'<Ctrl-a>': 'ctrla',
def setUpModule():
"""Mock out some imports in basekeyparser."""
basekeyparser.QObject = Mock()
basekeyparser.QObject = mock.Mock()
logging.disable(logging.WARNING)
@ -99,8 +99,8 @@ class ReadConfigTests(unittest.TestCase):
"""Test reading the config."""
def setUp(self):
basekeyparser.config = ConfigStub(CONFIG)
basekeyparser.Timer = Mock()
basekeyparser.config = stubs.ConfigStub(CONFIG)
basekeyparser.usertypes.Timer = mock.Mock()
def test_read_config_invalid(self):
"""Test reading config without setting it before."""
@ -131,31 +131,32 @@ class SpecialKeysTests(unittest.TestCase):
"""
def setUp(self):
patcher = patch('qutebrowser.keyinput.basekeyparser.Timer',
autospec=True)
patcher = mock.patch(
'qutebrowser.keyinput.basekeyparser.usertypes.Timer',
autospec=True)
patcher.start()
self.addCleanup(patcher.stop)
basekeyparser.config = ConfigStub(CONFIG)
basekeyparser.config = stubs.ConfigStub(CONFIG)
self.kp = basekeyparser.BaseKeyParser()
self.kp.execute = Mock()
self.kp.execute = mock.Mock()
self.kp.read_config('test')
def test_valid_key(self):
"""Test a valid special keyevent."""
self.kp.handle(fake_keyevent(Qt.Key_A, Qt.ControlModifier))
self.kp.handle(fake_keyevent(Qt.Key_X, Qt.ControlModifier))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, Qt.ControlModifier))
self.kp.handle(helpers.fake_keyevent(Qt.Key_X, Qt.ControlModifier))
self.kp.execute.assert_called_once_with('ctrla', self.kp.Type.special)
def test_invalid_key(self):
"""Test an invalid special keyevent."""
self.kp.handle(fake_keyevent(Qt.Key_A, (Qt.ControlModifier |
Qt.AltModifier)))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, (Qt.ControlModifier |
Qt.AltModifier)))
self.assertFalse(self.kp.execute.called)
def test_keychain(self):
"""Test a keychain."""
self.kp.handle(fake_keyevent(Qt.Key_B))
self.kp.handle(fake_keyevent(Qt.Key_A))
self.kp.handle(helpers.fake_keyevent(Qt.Key_B))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A))
self.assertFalse(self.kp.execute.called)
@ -170,35 +171,35 @@ class KeyChainTests(unittest.TestCase):
def setUp(self):
"""Set up mocks and read the test config."""
basekeyparser.config = ConfigStub(CONFIG)
self.timermock = Mock()
basekeyparser.Timer = Mock(return_value=self.timermock)
basekeyparser.config = stubs.ConfigStub(CONFIG)
self.timermock = mock.Mock()
basekeyparser.usertypes.Timer = mock.Mock(return_value=self.timermock)
self.kp = basekeyparser.BaseKeyParser(supports_chains=True,
supports_count=False)
self.kp.execute = Mock()
self.kp.execute = mock.Mock()
self.kp.read_config('test')
def test_valid_special_key(self):
"""Test valid special key."""
self.kp.handle(fake_keyevent(Qt.Key_A, Qt.ControlModifier))
self.kp.handle(fake_keyevent(Qt.Key_X, Qt.ControlModifier))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, Qt.ControlModifier))
self.kp.handle(helpers.fake_keyevent(Qt.Key_X, Qt.ControlModifier))
self.kp.execute.assert_called_once_with('ctrla', self.kp.Type.special)
self.assertEqual(self.kp._keystring, '')
def test_invalid_special_key(self):
"""Test invalid special key."""
self.kp.handle(fake_keyevent(Qt.Key_A, (Qt.ControlModifier |
Qt.AltModifier)))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, (Qt.ControlModifier |
Qt.AltModifier)))
self.assertFalse(self.kp.execute.called)
self.assertEqual(self.kp._keystring, '')
def test_keychain(self):
"""Test valid keychain."""
# Press 'x' which is ignored because of no match
self.kp.handle(fake_keyevent(Qt.Key_X, text='x'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_X, text='x'))
# Then start the real chain
self.kp.handle(fake_keyevent(Qt.Key_B, text='b'))
self.kp.handle(fake_keyevent(Qt.Key_A, text='a'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='b'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='a'))
self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, None)
self.assertEqual(self.kp._keystring, '')
@ -206,9 +207,10 @@ class KeyChainTests(unittest.TestCase):
"""Test ambigious keychain."""
# We start with 'a' where the keychain gives us an ambigious result.
# Then we check if the timer has been set up correctly
self.kp.handle(fake_keyevent(Qt.Key_A, text='a'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='a'))
self.assertFalse(self.kp.execute.called)
basekeyparser.Timer.assert_called_once_with(self.kp, 'ambigious_match')
basekeyparser.usertypes.Timer.assert_called_once_with(
self.kp, 'ambigious_match')
self.timermock.setSingleShot.assert_called_once_with(True)
self.timermock.setInterval.assert_called_once_with(100)
self.assertTrue(self.timermock.timeout.connect.called)
@ -216,15 +218,15 @@ class KeyChainTests(unittest.TestCase):
self.timermock.start.assert_called_once_with()
# Now we type an 'x' and check 'ax' has been executed and the timer
# stopped.
self.kp.handle(fake_keyevent(Qt.Key_X, text='x'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_X, text='x'))
self.kp.execute.assert_called_once_with('ax', self.kp.Type.chain, None)
self.timermock.stop.assert_called_once_with()
self.assertEqual(self.kp._keystring, '')
def test_invalid_keychain(self):
"""Test invalid keychain."""
self.kp.handle(fake_keyevent(Qt.Key_B, text='b'))
self.kp.handle(fake_keyevent(Qt.Key_C, text='c'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='b'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_C, text='c'))
self.assertEqual(self.kp._keystring, '')
@ -233,53 +235,53 @@ class CountTests(unittest.TestCase):
"""Test execute() with counts."""
def setUp(self):
basekeyparser.config = ConfigStub(CONFIG)
basekeyparser.Timer = Mock()
basekeyparser.config = stubs.ConfigStub(CONFIG)
basekeyparser.usertypes.Timer = mock.Mock()
self.kp = basekeyparser.BaseKeyParser(supports_chains=True,
supports_count=True)
self.kp.execute = Mock()
self.kp.execute = mock.Mock()
self.kp.read_config('test')
def test_no_count(self):
"""Test with no count added."""
self.kp.handle(fake_keyevent(Qt.Key_B, text='b'))
self.kp.handle(fake_keyevent(Qt.Key_A, text='a'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='b'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='a'))
self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, None)
self.assertEqual(self.kp._keystring, '')
def test_count_0(self):
"""Test with count=0."""
self.kp.handle(fake_keyevent(Qt.Key_0, text='0'))
self.kp.handle(fake_keyevent(Qt.Key_B, text='b'))
self.kp.handle(fake_keyevent(Qt.Key_A, text='a'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_0, text='0'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='b'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='a'))
self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, 0)
self.assertEqual(self.kp._keystring, '')
def test_count_42(self):
"""Test with count=42."""
self.kp.handle(fake_keyevent(Qt.Key_4, text='4'))
self.kp.handle(fake_keyevent(Qt.Key_2, text='2'))
self.kp.handle(fake_keyevent(Qt.Key_B, text='b'))
self.kp.handle(fake_keyevent(Qt.Key_A, text='a'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_4, text='4'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_2, text='2'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='b'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='a'))
self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, 42)
self.assertEqual(self.kp._keystring, '')
def test_count_42_invalid(self):
"""Test with count=42 and invalid command."""
# Invalid call with ccx gets ignored
self.kp.handle(fake_keyevent(Qt.Key_4, text='4'))
self.kp.handle(fake_keyevent(Qt.Key_2, text='2'))
self.kp.handle(fake_keyevent(Qt.Key_B, text='c'))
self.kp.handle(fake_keyevent(Qt.Key_A, text='c'))
self.kp.handle(fake_keyevent(Qt.Key_A, text='x'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_4, text='4'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_2, text='2'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='c'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='c'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='x'))
self.assertFalse(self.kp.execute.called)
self.assertEqual(self.kp._keystring, '')
# Valid call with ccc gets the correct count
self.kp.handle(fake_keyevent(Qt.Key_4, text='2'))
self.kp.handle(fake_keyevent(Qt.Key_2, text='3'))
self.kp.handle(fake_keyevent(Qt.Key_B, text='c'))
self.kp.handle(fake_keyevent(Qt.Key_A, text='c'))
self.kp.handle(fake_keyevent(Qt.Key_A, text='c'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_4, text='2'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_2, text='3'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='c'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='c'))
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='c'))
self.kp.execute.assert_called_once_with('ccc', self.kp.Type.chain, 23)
self.assertEqual(self.kp._keystring, '')

View File

@ -21,7 +21,7 @@
"""Fake objects/stubs."""
from unittest.mock import Mock
from unittest import mock
from PyQt5.QtCore import QPoint, QProcess
from PyQt5.QtWebKit import QWebElement
@ -73,9 +73,9 @@ class FakeKeyEvent:
"""Fake QKeyPressEvent stub."""
def __init__(self, key, modifiers=0, text=''):
self.key = Mock(return_value=key)
self.text = Mock(return_value=text)
self.modifiers = Mock(return_value=modifiers)
self.key = mock.Mock(return_value=key)
self.text = mock.Mock(return_value=text)
self.modifiers = mock.Mock(return_value=modifiers)
class FakeWebElement:
@ -99,10 +99,10 @@ class FakeWebElement:
Raise:
ValueError if element is not null and geometry/frame are not given.
"""
self.geometry = Mock(return_value=geometry)
self.webFrame = Mock(return_value=frame)
self.isNull = Mock(return_value=null)
self.tagName = Mock(return_value=tagname)
self.geometry = mock.Mock(return_value=geometry)
self.webFrame = mock.Mock(return_value=frame)
self.isNull = mock.Mock(return_value=null)
self.tagName = mock.Mock(return_value=tagname)
self._visibility = visibility
self._display = display
self._attributes = attributes
@ -170,9 +170,9 @@ class FakeWebFrame:
"""
if scroll is None:
scroll = QPoint(0, 0)
self.geometry = Mock(return_value=geometry)
self.scrollPosition = Mock(return_value=scroll)
self.parentFrame = Mock(return_value=parent)
self.geometry = mock.Mock(return_value=geometry)
self.scrollPosition = mock.Mock(return_value=scroll)
self.parentFrame = mock.Mock(return_value=parent)
class FakeChildrenFrame:
@ -182,7 +182,7 @@ class FakeChildrenFrame:
def __init__(self, children=None):
if children is None:
children = []
self.childFrames = Mock(return_value=children)
self.childFrames = mock.Mock(return_value=children)
class FakeQApplication:
@ -190,8 +190,8 @@ class FakeQApplication:
"""Stub to insert as QApplication module."""
def __init__(self, focus):
self.focusWidget = Mock(return_value=focus)
self.instance = Mock(return_value=self)
self.focusWidget = mock.Mock(return_value=focus)
self.instance = mock.Mock(return_value=self)
class FakeUrl:
@ -199,7 +199,7 @@ class FakeUrl:
"""QUrl stub which provides .path()."""
def __init__(self, path=None):
self.path = Mock(return_value=path)
self.path = mock.Mock(return_value=path)
class FakeNetworkReply:
@ -217,7 +217,7 @@ class FakeNetworkReply:
self.headers = {}
else:
self.headers = headers
self.url = Mock(return_value=url)
self.url = mock.Mock(return_value=url)
def hasRawHeader(self, name):
"""Check if the reply has a certain header.
@ -282,9 +282,9 @@ class FakeQProcess:
UnknownError = QProcess.UnknownError
def __init__(self, parent=None): # pylint: disable=unused-argument
self.finished = Mock()
self.error = Mock()
self.start = Mock()
self.finished = mock.Mock()
self.error = mock.Mock()
self.start = mock.Mock()
class FakeSignal:

View File

@ -23,7 +23,7 @@
import os
import unittest
from qutebrowser.test.helpers import environ_set_temp
from qutebrowser.test import helpers
class TestEnvironSetTemp(unittest.TestCase):
@ -33,13 +33,13 @@ class TestEnvironSetTemp(unittest.TestCase):
def test_environ_set(self):
"""Test environ_set_temp with something which was set already."""
os.environ['QUTEBROWSER_ENVIRON_TEST'] = 'oldval'
with environ_set_temp('QUTEBROWSER_ENVIRON_TEST', 'newval'):
with helpers.environ_set_temp('QUTEBROWSER_ENVIRON_TEST', 'newval'):
self.assertEqual(os.environ['QUTEBROWSER_ENVIRON_TEST'], 'newval')
self.assertEqual(os.environ['QUTEBROWSER_ENVIRON_TEST'], 'oldval')
def test_environ_unset(self):
"""Test environ_set_temp with something which wasn't set yet."""
with environ_set_temp('QUTEBROWSER_ENVIRON_TEST', 'newval'):
with helpers.environ_set_temp('QUTEBROWSER_ENVIRON_TEST', 'newval'):
self.assertEqual(os.environ['QUTEBROWSER_ENVIRON_TEST'], 'newval')
self.assertNotIn('QUTEBROWSER_ENVIRON_TEST', os.environ)

View File

@ -23,8 +23,8 @@ import os
import unittest
import logging
import qutebrowser.utils.http as httputils
from qutebrowser.test.stubs import FakeNetworkReply
from qutebrowser.utils import http
from qutebrowser.test import stubs
DEFAULT_NAME = 'qutebrowser-download'
@ -39,23 +39,23 @@ class AttachmentTestCase(unittest.TestCase):
def _check_filename(self, header, filename):
"""Check if the passed header has the given filename."""
reply = FakeNetworkReply(headers={'Content-Disposition': header})
cd_inline, cd_filename = httputils.parse_content_disposition(reply)
reply = stubs.FakeNetworkReply(headers={'Content-Disposition': header})
cd_inline, cd_filename = http.parse_content_disposition(reply)
self.assertIsNotNone(cd_filename)
self.assertEqual(cd_filename, filename)
self.assertFalse(cd_inline)
def _check_ignored(self, header):
"""Check if the passed header is ignored."""
reply = FakeNetworkReply(headers={'Content-Disposition': header})
cd_inline, cd_filename = httputils.parse_content_disposition(reply)
reply = stubs.FakeNetworkReply(headers={'Content-Disposition': header})
cd_inline, cd_filename = http.parse_content_disposition(reply)
self.assertEqual(cd_filename, DEFAULT_NAME)
self.assertTrue(cd_inline)
def _check_unnamed(self, header):
"""Check if the passed header results in an unnamed attachment."""
reply = FakeNetworkReply(headers={'Content-Disposition': header})
cd_inline, cd_filename = httputils.parse_content_disposition(reply)
reply = stubs.FakeNetworkReply(headers={'Content-Disposition': header})
cd_inline, cd_filename = http.parse_content_disposition(reply)
self.assertEqual(cd_filename, DEFAULT_NAME)
self.assertFalse(cd_inline)
@ -69,15 +69,15 @@ class InlineTests(unittest.TestCase):
def _check_filename(self, header, filename):
"""Check if the passed header has the given filename."""
reply = FakeNetworkReply(headers={'Content-Disposition': header})
cd_inline, cd_filename = httputils.parse_content_disposition(reply)
reply = stubs.FakeNetworkReply(headers={'Content-Disposition': header})
cd_inline, cd_filename = http.parse_content_disposition(reply)
self.assertEqual(cd_filename, filename)
self.assertTrue(cd_inline)
def _check_ignored(self, header):
"""Check if the passed header is ignored."""
reply = FakeNetworkReply(headers={'Content-Disposition': header})
cd_inline, cd_filename = httputils.parse_content_disposition(reply)
reply = stubs.FakeNetworkReply(headers={'Content-Disposition': header})
cd_inline, cd_filename = http.parse_content_disposition(reply)
self.assertEqual(cd_filename, DEFAULT_NAME)
self.assertTrue(cd_inline)
@ -134,8 +134,9 @@ class AttachmentTests(AttachmentTestCase):
UA should offer to download the resource.
"""
reply = FakeNetworkReply(headers={'Content-Disposition': 'attachment'})
cd_inline, cd_filename = httputils.parse_content_disposition(reply)
reply = stubs.FakeNetworkReply(
headers={'Content-Disposition': 'attachment'})
cd_inline, cd_filename = http.parse_content_disposition(reply)
self.assertFalse(cd_inline)
self.assertEqual(cd_filename, DEFAULT_NAME)

View File

@ -25,8 +25,8 @@ test_content_disposition.py file.
import unittest
import qutebrowser.utils.http as httputils
from qutebrowser.test.stubs import FakeNetworkReply
from qutebrowser.utils import http
from qutebrowser.test import stubs
class ParseContentTypeTests(unittest.TestCase):
@ -35,30 +35,31 @@ class ParseContentTypeTests(unittest.TestCase):
def test_not_existing(self):
"""Test without any Content-Type header."""
reply = FakeNetworkReply()
mimetype, rest = httputils.parse_content_type(reply)
reply = stubs.FakeNetworkReply()
mimetype, rest = http.parse_content_type(reply)
self.assertIsNone(mimetype)
self.assertIsNone(rest)
def test_mimetype(self):
"""Test with simple Content-Type header."""
reply = FakeNetworkReply(headers={'Content-Type': 'image/example'})
mimetype, rest = httputils.parse_content_type(reply)
reply = stubs.FakeNetworkReply(
headers={'Content-Type': 'image/example'})
mimetype, rest = http.parse_content_type(reply)
self.assertEqual(mimetype, 'image/example')
self.assertIsNone(rest)
def test_empty(self):
"""Test with empty Content-Type header."""
reply = FakeNetworkReply(headers={'Content-Type': ''})
mimetype, rest = httputils.parse_content_type(reply)
reply = stubs.FakeNetworkReply(headers={'Content-Type': ''})
mimetype, rest = http.parse_content_type(reply)
self.assertEqual(mimetype, '')
self.assertIsNone(rest)
def test_additional(self):
"""Test with Content-Type header with additional informations."""
reply = FakeNetworkReply(
reply = stubs.FakeNetworkReply(
headers={'Content-Type': 'image/example; encoding=UTF-8'})
mimetype, rest = httputils.parse_content_type(reply)
mimetype, rest = http.parse_content_type(reply)
self.assertEqual(mimetype, 'image/example')
self.assertEqual(rest, ' encoding=UTF-8')

View File

@ -24,8 +24,8 @@ import unittest
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QStyle, QFrame
import qutebrowser.utils.debug as debug
from qutebrowser.test.stubs import FakeSignal
from qutebrowser.utils import debug
from qutebrowser.test import stubs
class QEnumKeyTests(unittest.TestCase):
@ -123,7 +123,7 @@ class TestDebug(unittest.TestCase):
"""Test signal debug output functions."""
def setUp(self):
self.signal = FakeSignal()
self.signal = stubs.FakeSignal()
def test_signal_name(self):
"""Test signal_name()."""

View File

@ -23,19 +23,19 @@ import os
import os.path
import unittest
import logging
from unittest.mock import Mock
from unittest import mock
from PyQt5.QtCore import QProcess
import qutebrowser.utils.editor as editorutils
from qutebrowser.test.stubs import ConfigStub, FakeQProcess
from qutebrowser.utils import editor
from qutebrowser.test import stubs
def setUpModule():
"""Disable logging and mock out some imports."""
logging.disable(logging.INFO)
editorutils.message = Mock()
editorutils.QProcess = FakeQProcess
editor.message = mock.Mock()
editor.QProcess = stubs.FakeQProcess
def tearDownModule():
@ -52,18 +52,18 @@ class ArgTests(unittest.TestCase):
"""
def setUp(self):
self.editor = editorutils.ExternalEditor()
self.editor = editor.ExternalEditor()
def test_simple_start_args(self):
"""Test starting editor without arguments."""
editorutils.config = ConfigStub(
editor.config = stubs.ConfigStub(
{'general': {'editor': ['bin'], 'editor-encoding': 'utf-8'}})
self.editor.edit("")
self.editor.proc.start.assert_called_with("bin", [])
def test_start_args(self):
"""Test starting editor with static arguments."""
editorutils.config = ConfigStub(
editor.config = stubs.ConfigStub(
{'general': {'editor': ['bin', 'foo', 'bar'],
'editor-encoding': 'utf-8'}})
self.editor.edit("")
@ -71,7 +71,7 @@ class ArgTests(unittest.TestCase):
def test_placeholder(self):
"""Test starting editor with placeholder argument."""
editorutils.config = ConfigStub(
editor.config = stubs.ConfigStub(
{'general': {'editor': ['bin', 'foo', '{}', 'bar'],
'editor-encoding': 'utf-8'}})
self.editor.edit("")
@ -81,7 +81,7 @@ class ArgTests(unittest.TestCase):
def test_in_arg_placeholder(self):
"""Test starting editor with placeholder argument inside argument."""
editorutils.config = ConfigStub(
editor.config = stubs.ConfigStub(
{'general': {'editor': ['bin', 'foo{}bar'],
'editor-encoding': 'utf-8'}})
self.editor.edit("")
@ -100,8 +100,8 @@ class FileHandlingTests(unittest.TestCase):
"""
def setUp(self):
self.editor = editorutils.ExternalEditor()
editorutils.config = ConfigStub(
self.editor = editor.ExternalEditor()
editor.config = stubs.ConfigStub(
{'general': {'editor': [''], 'editor-encoding': 'utf-8'}})
def test_file_handling_closed_ok(self):
@ -139,9 +139,9 @@ class TextModifyTests(unittest.TestCase):
"""
def setUp(self):
self.editor = editorutils.ExternalEditor()
self.editor.editing_finished = Mock()
editorutils.config = ConfigStub(
self.editor = editor.ExternalEditor()
self.editor.editing_finished = mock.Mock()
editor.config = stubs.ConfigStub(
{'general': {'editor': [''], 'editor-encoding': 'utf-8'}})
def _write(self, text):
@ -209,21 +209,21 @@ class ErrorMessageTests(unittest.TestCase):
# pylint: disable=maybe-no-member
def setUp(self):
self.editor = editorutils.ExternalEditor()
editorutils.config = ConfigStub(
self.editor = editor.ExternalEditor()
editor.config = stubs.ConfigStub(
{'general': {'editor': [''], 'editor-encoding': 'utf-8'}})
def test_proc_error(self):
"""Test on_proc_error."""
self.editor.edit("")
self.editor.on_proc_error(QProcess.Crashed)
self.assertTrue(editorutils.message.error.called)
self.assertTrue(editor.message.error.called)
def test_proc_return(self):
"""Test on_proc_finished with a bad exit status."""
self.editor.edit("")
self.editor.on_proc_closed(1, QProcess.NormalExit)
self.assertTrue(editorutils.message.error.called)
self.assertTrue(editor.message.error.called)
if __name__ == '__main__':

View File

@ -26,7 +26,7 @@ import unittest
import argparse
import sys
import qutebrowser.utils.log as log
from qutebrowser.utils import log
class BaseTest(unittest.TestCase):

View File

@ -24,14 +24,14 @@ import sys
import shutil
import unittest
import os.path
from tempfile import mkdtemp
import tempfile
from PyQt5.QtCore import QStandardPaths, QCoreApplication, Qt
from PyQt5.QtGui import QColor
import qutebrowser.utils.misc as utils
from qutebrowser.test.helpers import environ_set_temp, fake_keyevent
from qutebrowser.utils.qt import QtValueError
from qutebrowser.utils import misc as utils
from qutebrowser.utils import qt as qtutils
from qutebrowser.test import helpers
class Color(QColor):
@ -157,14 +157,14 @@ class GetStandardDirLinuxTests(unittest.TestCase):
"""
def setUp(self):
self.temp_dir = mkdtemp()
self.temp_dir = tempfile.mkdtemp()
self.app = QCoreApplication([])
self.app.setApplicationName('qutebrowser')
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
def test_data_explicit(self):
"""Test data dir with XDG_DATA_HOME explicitely set."""
with environ_set_temp('XDG_DATA_HOME', self.temp_dir):
with helpers.environ_set_temp('XDG_DATA_HOME', self.temp_dir):
cur_dir = utils.get_standard_dir(QStandardPaths.DataLocation)
self.assertEqual(cur_dir, os.path.join(self.temp_dir,
'qutebrowser'))
@ -173,7 +173,7 @@ class GetStandardDirLinuxTests(unittest.TestCase):
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
def test_config_explicit(self):
"""Test config dir with XDG_CONFIG_HOME explicitely set."""
with environ_set_temp('XDG_CONFIG_HOME', self.temp_dir):
with helpers.environ_set_temp('XDG_CONFIG_HOME', self.temp_dir):
cur_dir = utils.get_standard_dir(QStandardPaths.ConfigLocation)
self.assertEqual(cur_dir, os.path.join(self.temp_dir,
'qutebrowser'))
@ -182,7 +182,7 @@ class GetStandardDirLinuxTests(unittest.TestCase):
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
def test_cache_explicit(self):
"""Test cache dir with XDG_CACHE_HOME explicitely set."""
with environ_set_temp('XDG_CACHE_HOME', self.temp_dir):
with helpers.environ_set_temp('XDG_CACHE_HOME', self.temp_dir):
cur_dir = utils.get_standard_dir(QStandardPaths.CacheLocation)
self.assertEqual(cur_dir, os.path.join(self.temp_dir,
'qutebrowser'))
@ -191,7 +191,7 @@ class GetStandardDirLinuxTests(unittest.TestCase):
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
def test_data(self):
"""Test data dir with XDG_DATA_HOME not set."""
with environ_set_temp('HOME', self.temp_dir):
with helpers.environ_set_temp('HOME', self.temp_dir):
cur_dir = utils.get_standard_dir(QStandardPaths.DataLocation)
self.assertEqual(cur_dir, os.path.join(self.temp_dir, '.local',
'share', 'qutebrowser'))
@ -200,7 +200,7 @@ class GetStandardDirLinuxTests(unittest.TestCase):
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
def test_config(self):
"""Test config dir with XDG_CONFIG_HOME not set."""
with environ_set_temp('HOME', self.temp_dir):
with helpers.environ_set_temp('HOME', self.temp_dir):
cur_dir = utils.get_standard_dir(
QStandardPaths.ConfigLocation)
self.assertEqual(cur_dir, os.path.join(self.temp_dir, '.config',
@ -210,7 +210,7 @@ class GetStandardDirLinuxTests(unittest.TestCase):
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
def test_cache(self):
"""Test cache dir with XDG_CACHE_HOME not set."""
with environ_set_temp('HOME', self.temp_dir):
with helpers.environ_set_temp('HOME', self.temp_dir):
cur_dir = utils.get_standard_dir(QStandardPaths.CacheLocation)
self.assertEqual(cur_dir, os.path.join(self.temp_dir, '.cache',
'qutebrowser'))
@ -286,12 +286,12 @@ class InterpolateColorTests(unittest.TestCase):
def test_invalid_start(self):
"""Test an invalid start color."""
with self.assertRaises(QtValueError):
with self.assertRaises(qtutils.QtValueError):
utils.interpolate_color(Color(), self.white, 0)
def test_invalid_end(self):
"""Test an invalid end color."""
with self.assertRaises(QtValueError):
with self.assertRaises(qtutils.QtValueError):
utils.interpolate_color(self.white, Color(), 0)
def test_invalid_percentage(self):
@ -464,29 +464,31 @@ class KeyEventToStringTests(unittest.TestCase):
def test_only_control(self):
"""Test keyeevent when only control is pressed."""
evt = fake_keyevent(key=Qt.Key_Control, modifiers=Qt.ControlModifier)
evt = helpers.fake_keyevent(key=Qt.Key_Control,
modifiers=Qt.ControlModifier)
self.assertIsNone(utils.keyevent_to_string(evt))
def test_only_hyper_l(self):
"""Test keyeevent when only Hyper_L is pressed."""
evt = fake_keyevent(key=Qt.Key_Hyper_L, modifiers=Qt.MetaModifier)
evt = helpers.fake_keyevent(key=Qt.Key_Hyper_L,
modifiers=Qt.MetaModifier)
self.assertIsNone(utils.keyevent_to_string(evt))
def test_only_key(self):
"""Test with a simple key pressed."""
evt = fake_keyevent(key=Qt.Key_A)
evt = helpers.fake_keyevent(key=Qt.Key_A)
self.assertEqual(utils.keyevent_to_string(evt), 'A')
def test_key_and_modifier(self):
"""Test with key and modifier pressed."""
evt = fake_keyevent(key=Qt.Key_A, modifiers=Qt.ControlModifier)
evt = helpers.fake_keyevent(key=Qt.Key_A, modifiers=Qt.ControlModifier)
self.assertEqual(utils.keyevent_to_string(evt), 'Ctrl+A')
def test_key_and_modifiers(self):
"""Test with key and multiple modifier pressed."""
evt = fake_keyevent(key=Qt.Key_A,
modifiers=(Qt.ControlModifier | Qt.AltModifier |
Qt.MetaModifier | Qt.ShiftModifier))
evt = helpers.fake_keyevent(
key=Qt.Key_A, modifiers=(Qt.ControlModifier | Qt.AltModifier |
Qt.MetaModifier | Qt.ShiftModifier))
self.assertEqual(utils.keyevent_to_string(evt),
'Ctrl+Alt+Meta+Shift+A')

View File

@ -23,7 +23,7 @@ import sys
import argparse
import unittest
import qutebrowser.utils.qt as qt
from qutebrowser.utils import qt
class CheckOverflowTests(unittest.TestCase):

View File

@ -21,12 +21,12 @@
import inspect
import unittest
from unittest.mock import Mock
from unittest import mock
from PyQt5.QtWidgets import QLineEdit
import qutebrowser.utils.readline as readline
from qutebrowser.test.stubs import FakeQApplication
from qutebrowser.utils import readline
from qutebrowser.test import stubs
class NoneWidgetTests(unittest.TestCase):
@ -34,7 +34,7 @@ class NoneWidgetTests(unittest.TestCase):
"""Tests when the focused widget is None."""
def setUp(self):
readline.QApplication = FakeQApplication(None)
readline.QApplication = stubs.FakeQApplication(None)
self.bridge = readline.ReadlineBridge()
def test_none(self):
@ -50,9 +50,9 @@ class ReadlineBridgeTest(unittest.TestCase):
"""Tests for readline bridge."""
def setUp(self):
self.qle = Mock()
self.qle = mock.Mock()
self.qle.__class__ = QLineEdit
readline.QApplication = FakeQApplication(self.qle)
readline.QApplication = stubs.FakeQApplication(self.qle)
self.bridge = readline.ReadlineBridge()
def _set_selected_text(self, text):

View File

@ -25,8 +25,8 @@ import unittest
from PyQt5.QtCore import QUrl
import qutebrowser.utils.url as urlutils
from qutebrowser.test.stubs import ConfigStub
from qutebrowser.utils import url as urlutils
from qutebrowser.test import stubs
CONFIG = {
@ -83,7 +83,7 @@ class SearchUrlTests(unittest.TestCase):
def setUp(self):
self.config = urlutils.config
urlutils.config = ConfigStub(CONFIG)
urlutils.config = stubs.ConfigStub(CONFIG)
def test_default_engine(self):
"""Test default search engine."""

View File

@ -23,9 +23,8 @@ import unittest
from PyQt5.QtCore import QRect, QPoint
import qutebrowser.utils.webelem as webelem
from qutebrowser.test.stubs import (FakeWebElement, FakeWebFrame,
FakeChildrenFrame, ConfigStub)
from qutebrowser.utils import webelem
from qutebrowser.test import stubs
class IsVisibleInvalidTests(unittest.TestCase):
@ -37,7 +36,7 @@ class IsVisibleInvalidTests(unittest.TestCase):
"""
def setUp(self):
self.frame = FakeWebFrame(QRect(0, 0, 100, 100))
self.frame = stubs.FakeWebFrame(QRect(0, 0, 100, 100))
def test_nullelem(self):
"""Passing an element with isNull() == True.
@ -45,7 +44,7 @@ class IsVisibleInvalidTests(unittest.TestCase):
geometry() and webFrame() should not be called, and ValueError should
be raised.
"""
elem = FakeWebElement(null=True)
elem = stubs.FakeWebElement(null=True)
with self.assertRaises(ValueError):
webelem.is_visible(elem, self.frame)
elem.isNull.assert_called_once_with()
@ -54,7 +53,7 @@ class IsVisibleInvalidTests(unittest.TestCase):
def test_invalid_invisible(self):
"""Test elements with an invalid geometry which are invisible."""
elem = FakeWebElement(QRect(0, 0, 0, 0), self.frame)
elem = stubs.FakeWebElement(QRect(0, 0, 0, 0), self.frame)
self.assertFalse(elem.geometry().isValid())
self.assertEqual(elem.geometry().x(), 0)
self.assertFalse(webelem.is_visible(elem, self.frame))
@ -65,7 +64,7 @@ class IsVisibleInvalidTests(unittest.TestCase):
This seems to happen sometimes in the real world, with real elements
which *are* visible, but don't have a valid geometry.
"""
elem = FakeWebElement(QRect(10, 10, 0, 0), self.frame)
elem = stubs.FakeWebElement(QRect(10, 10, 0, 0), self.frame)
self.assertFalse(elem.geometry().isValid())
self.assertTrue(webelem.is_visible(elem, self.frame))
@ -79,16 +78,17 @@ class IsVisibleScrollTests(unittest.TestCase):
"""
def setUp(self):
self.frame = FakeWebFrame(QRect(0, 0, 100, 100), scroll=QPoint(10, 10))
self.frame = stubs.FakeWebFrame(QRect(0, 0, 100, 100),
scroll=QPoint(10, 10))
def test_invisible(self):
"""Test elements which should be invisible due to scrolling."""
elem = FakeWebElement(QRect(5, 5, 4, 4), self.frame)
elem = stubs.FakeWebElement(QRect(5, 5, 4, 4), self.frame)
self.assertFalse(webelem.is_visible(elem, self.frame))
def test_visible(self):
"""Test elements which still should be visible after scrolling."""
elem = FakeWebElement(QRect(10, 10, 1, 1), self.frame)
elem = stubs.FakeWebElement(QRect(10, 10, 1, 1), self.frame)
self.assertTrue(webelem.is_visible(elem, self.frame))
@ -101,29 +101,30 @@ class IsVisibleCssTests(unittest.TestCase):
"""
def setUp(self):
self.frame = FakeWebFrame(QRect(0, 0, 100, 100))
self.frame = stubs.FakeWebFrame(QRect(0, 0, 100, 100))
def test_visibility_visible(self):
"""Check that elements with "visibility = visible" are visible."""
elem = FakeWebElement(QRect(0, 0, 10, 10), self.frame,
visibility='visible')
elem = stubs.FakeWebElement(QRect(0, 0, 10, 10), self.frame,
visibility='visible')
self.assertTrue(webelem.is_visible(elem, self.frame))
def test_visibility_hidden(self):
"""Check that elements with "visibility = hidden" are not visible."""
elem = FakeWebElement(QRect(0, 0, 10, 10), self.frame,
visibility='hidden')
elem = stubs.FakeWebElement(QRect(0, 0, 10, 10), self.frame,
visibility='hidden')
self.assertFalse(webelem.is_visible(elem, self.frame))
def test_display_inline(self):
"""Check that elements with "display = inline" are visible."""
elem = FakeWebElement(QRect(0, 0, 10, 10), self.frame,
display='inline')
elem = stubs.FakeWebElement(QRect(0, 0, 10, 10), self.frame,
display='inline')
self.assertTrue(webelem.is_visible(elem, self.frame))
def test_display_none(self):
"""Check that elements with "display = none" are not visible."""
elem = FakeWebElement(QRect(0, 0, 10, 10), self.frame, display='none')
elem = stubs.FakeWebElement(QRect(0, 0, 10, 10), self.frame,
display='none')
self.assertFalse(webelem.is_visible(elem, self.frame))
@ -158,12 +159,13 @@ class IsVisibleIframeTests(unittest.TestCase):
##############################
300, 0 300, 300
"""
self.frame = FakeWebFrame(QRect(0, 0, 300, 300))
self.iframe = FakeWebFrame(QRect(0, 10, 100, 100), parent=self.frame)
self.elem1 = FakeWebElement(QRect(0, 0, 10, 10), self.iframe)
self.elem2 = FakeWebElement(QRect(20, 90, 10, 10), self.iframe)
self.elem3 = FakeWebElement(QRect(20, 150, 10, 10), self.iframe)
self.elem4 = FakeWebElement(QRect(30, 180, 10, 10), self.frame)
self.frame = stubs.FakeWebFrame(QRect(0, 0, 300, 300))
self.iframe = stubs.FakeWebFrame(QRect(0, 10, 100, 100),
parent=self.frame)
self.elem1 = stubs.FakeWebElement(QRect(0, 0, 10, 10), self.iframe)
self.elem2 = stubs.FakeWebElement(QRect(20, 90, 10, 10), self.iframe)
self.elem3 = stubs.FakeWebElement(QRect(20, 150, 10, 10), self.iframe)
self.elem4 = stubs.FakeWebElement(QRect(30, 180, 10, 10), self.frame)
def test_not_scrolled(self):
"""Test base situation."""
@ -210,17 +212,17 @@ class IsWritableTests(unittest.TestCase):
def test_writable(self):
"""Test a normal element."""
elem = FakeWebElement()
elem = stubs.FakeWebElement()
self.assertTrue(webelem.is_writable(elem))
def test_disabled(self):
"""Test a disabled element."""
elem = FakeWebElement(attributes=['disabled'])
elem = stubs.FakeWebElement(attributes=['disabled'])
self.assertFalse(webelem.is_writable(elem))
def test_readonly(self):
"""Test a readonly element."""
elem = FakeWebElement(attributes=['readonly'])
elem = stubs.FakeWebElement(attributes=['readonly'])
self.assertFalse(webelem.is_writable(elem))
@ -252,7 +254,7 @@ class GetChildFramesTests(unittest.TestCase):
def test_single_frame(self):
"""Test get_child_frames with a single frame without children."""
frame = FakeChildrenFrame()
frame = stubs.FakeChildrenFrame()
children = webelem.get_child_frames(frame)
self.assertEqual(len(children), 1)
self.assertIs(children[0], frame)
@ -265,9 +267,9 @@ class GetChildFramesTests(unittest.TestCase):
/ \
child1 o o child2
"""
child1 = FakeChildrenFrame()
child2 = FakeChildrenFrame()
parent = FakeChildrenFrame([child1, child2])
child1 = stubs.FakeChildrenFrame()
child2 = stubs.FakeChildrenFrame()
parent = stubs.FakeChildrenFrame([child1, child2])
children = webelem.get_child_frames(parent)
self.assertEqual(len(children), 3)
self.assertIs(children[0], parent)
@ -286,10 +288,10 @@ class GetChildFramesTests(unittest.TestCase):
/\ /\
o o o o second
"""
second = [FakeChildrenFrame() for _ in range(4)]
first = [FakeChildrenFrame(second[0:2]),
FakeChildrenFrame(second[2:4])]
root = FakeChildrenFrame(first)
second = [stubs.FakeChildrenFrame() for _ in range(4)]
first = [stubs.FakeChildrenFrame(second[0:2]),
stubs.FakeChildrenFrame(second[2:4])]
root = stubs.FakeChildrenFrame(first)
children = webelem.get_child_frames(root)
self.assertEqual(len(children), 7)
self.assertIs(children[0], root)
@ -307,175 +309,189 @@ class IsEditableTests(unittest.TestCase):
def test_input_plain(self):
"""Test with plain input element."""
elem = FakeWebElement(tagname='input')
elem = stubs.FakeWebElement(tagname='input')
self.assertTrue(webelem.is_editable(elem))
def test_input_text(self):
"""Test with text input element."""
elem = FakeWebElement(tagname='input', attributes={'type': 'text'})
elem = stubs.FakeWebElement(tagname='input',
attributes={'type': 'text'})
self.assertTrue(webelem.is_editable(elem))
def test_input_text_caps(self):
"""Test with text input element with caps attributes."""
elem = FakeWebElement(tagname='INPUT', attributes={'TYPE': 'TEXT'})
elem = stubs.FakeWebElement(tagname='INPUT',
attributes={'TYPE': 'TEXT'})
self.assertTrue(webelem.is_editable(elem))
def test_input_email(self):
"""Test with email input element."""
elem = FakeWebElement(tagname='input', attributes={'type': 'email'})
elem = stubs.FakeWebElement(tagname='input',
attributes={'type': 'email'})
self.assertTrue(webelem.is_editable(elem))
def test_input_url(self):
"""Test with url input element."""
elem = FakeWebElement(tagname='input', attributes={'type': 'url'})
elem = stubs.FakeWebElement(tagname='input',
attributes={'type': 'url'})
self.assertTrue(webelem.is_editable(elem))
def test_input_tel(self):
"""Test with tel input element."""
elem = FakeWebElement(tagname='input', attributes={'type': 'tel'})
elem = stubs.FakeWebElement(tagname='input',
attributes={'type': 'tel'})
self.assertTrue(webelem.is_editable(elem))
def test_input_number(self):
"""Test with number input element."""
elem = FakeWebElement(tagname='input', attributes={'type': 'number'})
elem = stubs.FakeWebElement(tagname='input',
attributes={'type': 'number'})
self.assertTrue(webelem.is_editable(elem))
def test_input_password(self):
"""Test with password input element."""
elem = FakeWebElement(tagname='input', attributes={'type': 'password'})
elem = stubs.FakeWebElement(tagname='input',
attributes={'type': 'password'})
self.assertTrue(webelem.is_editable(elem))
def test_input_search(self):
"""Test with search input element."""
elem = FakeWebElement(tagname='input', attributes={'type': 'search'})
elem = stubs.FakeWebElement(tagname='input',
attributes={'type': 'search'})
self.assertTrue(webelem.is_editable(elem))
def test_input_button(self):
"""Button should not be editable."""
elem = FakeWebElement(tagname='input', attributes={'type': 'button'})
elem = stubs.FakeWebElement(tagname='input',
attributes={'type': 'button'})
self.assertFalse(webelem.is_editable(elem))
def test_input_checkbox(self):
"""Checkbox should not be editable."""
elem = FakeWebElement(tagname='input', attributes={'type': 'checkbox'})
elem = stubs.FakeWebElement(tagname='input',
attributes={'type': 'checkbox'})
self.assertFalse(webelem.is_editable(elem))
def test_textarea(self):
"""Test textarea element."""
elem = FakeWebElement(tagname='textarea')
elem = stubs.FakeWebElement(tagname='textarea')
self.assertTrue(webelem.is_editable(elem))
def test_select(self):
"""Test selectbox."""
elem = FakeWebElement(tagname='select')
elem = stubs.FakeWebElement(tagname='select')
self.assertFalse(webelem.is_editable(elem))
def test_input_disabled(self):
"""Test disabled input element."""
elem = FakeWebElement(tagname='input', attributes={'disabled': None})
elem = stubs.FakeWebElement(tagname='input',
attributes={'disabled': None})
self.assertFalse(webelem.is_editable(elem))
def test_input_readonly(self):
"""Test readonly input element."""
elem = FakeWebElement(tagname='input', attributes={'readonly': None})
elem = stubs.FakeWebElement(tagname='input',
attributes={'readonly': None})
self.assertFalse(webelem.is_editable(elem))
def test_textarea_disabled(self):
"""Test disabled textarea element."""
elem = FakeWebElement(tagname='textarea',
attributes={'disabled': None})
elem = stubs.FakeWebElement(tagname='textarea',
attributes={'disabled': None})
self.assertFalse(webelem.is_editable(elem))
def test_textarea_readonly(self):
"""Test readonly textarea element."""
elem = FakeWebElement(tagname='textarea',
attributes={'readonly': None})
elem = stubs.FakeWebElement(tagname='textarea',
attributes={'readonly': None})
self.assertFalse(webelem.is_editable(elem))
def test_embed_true(self):
"""Test embed-element with insert-mode-on-plugins true."""
webelem.config = ConfigStub({'input':
{'insert-mode-on-plugins': True}})
elem = FakeWebElement(tagname='embed')
webelem.config = stubs.ConfigStub({'input':
{'insert-mode-on-plugins': True}})
elem = stubs.FakeWebElement(tagname='embed')
self.assertTrue(webelem.is_editable(elem))
def test_applet_true(self):
"""Test applet-element with insert-mode-on-plugins true."""
webelem.config = ConfigStub({'input':
{'insert-mode-on-plugins': True}})
elem = FakeWebElement(tagname='applet')
webelem.config = stubs.ConfigStub({'input':
{'insert-mode-on-plugins': True}})
elem = stubs.FakeWebElement(tagname='applet')
self.assertTrue(webelem.is_editable(elem))
def test_embed_false(self):
"""Test embed-element with insert-mode-on-plugins false."""
webelem.config = ConfigStub({'input':
{'insert-mode-on-plugins': False}})
elem = FakeWebElement(tagname='embed')
webelem.config = stubs.ConfigStub({'input':
{'insert-mode-on-plugins': False}})
elem = stubs.FakeWebElement(tagname='embed')
self.assertFalse(webelem.is_editable(elem))
def test_applet_false(self):
"""Test applet-element with insert-mode-on-plugins false."""
webelem.config = ConfigStub({'input':
{'insert-mode-on-plugins': False}})
elem = FakeWebElement(tagname='applet')
webelem.config = stubs.ConfigStub({'input':
{'insert-mode-on-plugins': False}})
elem = stubs.FakeWebElement(tagname='applet')
self.assertFalse(webelem.is_editable(elem))
def test_object_no_type(self):
"""Test object-element without type."""
elem = FakeWebElement(tagname='object')
elem = stubs.FakeWebElement(tagname='object')
self.assertFalse(webelem.is_editable(elem))
def test_object_image(self):
"""Test object-element with image type."""
elem = FakeWebElement(tagname='object',
attributes={'type': 'image/gif'})
elem = stubs.FakeWebElement(tagname='object',
attributes={'type': 'image/gif'})
self.assertFalse(webelem.is_editable(elem))
def test_object_application(self):
"""Test object-element with application type."""
webelem.config = ConfigStub({'input':
{'insert-mode-on-plugins': True}})
elem = FakeWebElement(tagname='object',
attributes={'type': 'application/foo'})
webelem.config = stubs.ConfigStub({'input':
{'insert-mode-on-plugins': True}})
elem = stubs.FakeWebElement(tagname='object',
attributes={'type': 'application/foo'})
self.assertTrue(webelem.is_editable(elem))
def test_object_application_false(self):
"""Test object-element with application type but not ...-on-plugins."""
webelem.config = ConfigStub({'input':
{'insert-mode-on-plugins': False}})
elem = FakeWebElement(tagname='object',
attributes={'type': 'application/foo'})
webelem.config = stubs.ConfigStub({'input':
{'insert-mode-on-plugins': False}})
elem = stubs.FakeWebElement(tagname='object',
attributes={'type': 'application/foo'})
self.assertFalse(webelem.is_editable(elem))
def test_object_classid(self):
"""Test object-element with classid."""
webelem.config = ConfigStub({'input':
{'insert-mode-on-plugins': True}})
elem = FakeWebElement(tagname='object',
attributes={'type': 'foo', 'classid': 'foo'})
webelem.config = stubs.ConfigStub({'input':
{'insert-mode-on-plugins': True}})
elem = stubs.FakeWebElement(tagname='object',
attributes={'type': 'foo',
'classid': 'foo'})
self.assertTrue(webelem.is_editable(elem))
def test_object_classid_false(self):
"""Test object-element with classid but not insert-mode-on-plugins."""
webelem.config = ConfigStub({'input':
{'insert-mode-on-plugins': False}})
elem = FakeWebElement(tagname='object',
attributes={'type': 'foo', 'classid': 'foo'})
webelem.config = stubs.ConfigStub({'input':
{'insert-mode-on-plugins': False}})
elem = stubs.FakeWebElement(tagname='object',
attributes={'type': 'foo',
'classid': 'foo'})
self.assertFalse(webelem.is_editable(elem))
def test_div_empty(self):
"""Test div-element without class."""
elem = FakeWebElement(tagname='div')
elem = stubs.FakeWebElement(tagname='div')
self.assertFalse(webelem.is_editable(elem))
def test_div_noneditable(self):
"""Test div-element with non-editableclass."""
elem = FakeWebElement(tagname='div', classes='foo-kix-bar')
elem = stubs.FakeWebElement(tagname='div', classes='foo-kix-bar')
self.assertFalse(webelem.is_editable(elem))
def test_div_xik(self):
"""Test div-element with xik class."""
elem = FakeWebElement(tagname='div', classes='foo kix-foo')
elem = stubs.FakeWebElement(tagname='div', classes='foo kix-foo')
self.assertTrue(webelem.is_editable(elem))
def test_div_xik_caps(self):
@ -483,12 +499,13 @@ class IsEditableTests(unittest.TestCase):
This tests if classes are case sensitive as they should.
"""
elem = FakeWebElement(tagname='div', classes='KIX-FOO')
elem = stubs.FakeWebElement(tagname='div', classes='KIX-FOO')
self.assertFalse(webelem.is_editable(elem))
def test_div_codemirror(self):
"""Test div-element with codemirror class."""
elem = FakeWebElement(tagname='div', classes='foo CodeMirror-foo')
elem = stubs.FakeWebElement(tagname='div',
classes='foo CodeMirror-foo')
self.assertTrue(webelem.is_editable(elem))

View File

@ -21,7 +21,7 @@
import unittest
from qutebrowser.utils.usertypes import enum
from qutebrowser.utils import usertypes
# FIXME: Add some more tests, e.g. for is_int
@ -35,7 +35,7 @@ class EnumTests(unittest.TestCase):
"""
def setUp(self):
self.enum = enum('Enum', 'one', 'two')
self.enum = usertypes.enum('Enum', 'one', 'two')
def test_values(self):
"""Test if enum members resolve to the right values."""
@ -54,7 +54,7 @@ class EnumTests(unittest.TestCase):
def test_start(self):
"""Test the start= argument."""
e = enum('Enum', 'three', 'four', start=3)
e = usertypes.enum('Enum', 'three', 'four', start=3)
self.assertEqual(e.three.value, 3)
self.assertEqual(e.four.value, 4)

View File

@ -23,7 +23,7 @@
import unittest
from qutebrowser.utils.usertypes import NeighborList
from qutebrowser.utils import usertypes
class InitTests(unittest.TestCase):
@ -36,27 +36,27 @@ class InitTests(unittest.TestCase):
def test_empty(self):
"""Test constructing an empty NeighborList."""
nl = NeighborList()
nl = usertypes.NeighborList()
self.assertEqual(nl.items, [])
def test_items(self):
"""Test constructing an NeighborList with items."""
nl = NeighborList([1, 2, 3])
nl = usertypes.NeighborList([1, 2, 3])
self.assertEqual(nl.items, [1, 2, 3])
def test_len(self):
"""Test len() on NeighborList."""
nl = NeighborList([1, 2, 3])
nl = usertypes.NeighborList([1, 2, 3])
self.assertEqual(len(nl), 3)
def test_repr(self):
"""Test repr() on NeighborList."""
nl = NeighborList([1, 2, 3])
nl = usertypes.NeighborList([1, 2, 3])
self.assertEqual(repr(nl), 'NeighborList([1, 2, 3])')
def test_contains(self):
"""Test 'in' on NeighborList."""
nl = NeighborList([1, 2, 3])
nl = usertypes.NeighborList([1, 2, 3])
self.assertIn(2, nl)
self.assertNotIn(4, nl)
@ -71,17 +71,17 @@ class DefaultTests(unittest.TestCase):
def test_simple(self):
"""Test default with a numeric argument."""
nl = NeighborList([1, 2, 3], default=2)
nl = usertypes.NeighborList([1, 2, 3], default=2)
self.assertEqual(nl.idx, 1)
def test_none(self):
"""Test default 'None'."""
nl = NeighborList([1, 2, None], default=None)
nl = usertypes.NeighborList([1, 2, None], default=None)
self.assertEqual(nl.idx, 2)
def test_unset(self):
"""Test unset default value."""
nl = NeighborList([1, 2, 3])
nl = usertypes.NeighborList([1, 2, 3])
self.assertIsNone(nl.idx)
@ -94,7 +94,7 @@ class EmptyTests(unittest.TestCase):
"""
def setUp(self):
self.nl = NeighborList()
self.nl = usertypes.NeighborList()
def test_curitem(self):
"""Test curitem with no item."""
@ -126,7 +126,7 @@ class ItemTests(unittest.TestCase):
"""
def setUp(self):
self.nl = NeighborList([1, 2, 3, 4, 5], default=3)
self.nl = usertypes.NeighborList([1, 2, 3, 4, 5], default=3)
def test_curitem(self):
"""Test curitem()."""
@ -183,11 +183,11 @@ class OneTests(unittest.TestCase):
"""
def setUp(self):
self.nl = NeighborList([1], default=1)
self.nl = usertypes.NeighborList([1], default=1)
def test_first_wrap(self):
"""Test out of bounds previtem() with mode=wrap."""
self.nl._mode = NeighborList.Modes.wrap
self.nl._mode = usertypes.NeighborList.Modes.wrap
self.nl.firstitem()
self.assertEqual(self.nl.idx, 0)
self.assertEqual(self.nl.previtem(), 1)
@ -195,7 +195,7 @@ class OneTests(unittest.TestCase):
def test_first_block(self):
"""Test out of bounds previtem() with mode=block."""
self.nl._mode = NeighborList.Modes.block
self.nl._mode = usertypes.NeighborList.Modes.block
self.nl.firstitem()
self.assertEqual(self.nl.idx, 0)
self.assertEqual(self.nl.previtem(), 1)
@ -203,7 +203,7 @@ class OneTests(unittest.TestCase):
def test_first_raise(self):
"""Test out of bounds previtem() with mode=raise."""
self.nl._mode = NeighborList.Modes.exception
self.nl._mode = usertypes.NeighborList.Modes.exception
self.nl.firstitem()
self.assertEqual(self.nl.idx, 0)
with self.assertRaises(IndexError):
@ -212,7 +212,7 @@ class OneTests(unittest.TestCase):
def test_last_wrap(self):
"""Test out of bounds nextitem() with mode=wrap."""
self.nl._mode = NeighborList.Modes.wrap
self.nl._mode = usertypes.NeighborList.Modes.wrap
self.nl.lastitem()
self.assertEqual(self.nl.idx, 0)
self.assertEqual(self.nl.nextitem(), 1)
@ -220,7 +220,7 @@ class OneTests(unittest.TestCase):
def test_last_block(self):
"""Test out of bounds nextitem() with mode=block."""
self.nl._mode = NeighborList.Modes.block
self.nl._mode = usertypes.NeighborList.Modes.block
self.nl.lastitem()
self.assertEqual(self.nl.idx, 0)
self.assertEqual(self.nl.nextitem(), 1)
@ -228,7 +228,7 @@ class OneTests(unittest.TestCase):
def test_last_raise(self):
"""Test out of bounds nextitem() with mode=raise."""
self.nl._mode = NeighborList.Modes.exception
self.nl._mode = usertypes.NeighborList.Modes.exception
self.nl.lastitem()
self.assertEqual(self.nl.idx, 0)
with self.assertRaises(IndexError):
@ -245,8 +245,9 @@ class BlockTests(unittest.TestCase):
"""
def setUp(self):
self.nl = NeighborList([1, 2, 3, 4, 5], default=3,
mode=NeighborList.Modes.block)
self.nl = usertypes.NeighborList(
[1, 2, 3, 4, 5], default=3,
mode=usertypes.NeighborList.Modes.block)
def test_first(self):
"""Test ouf of bounds previtem()."""
@ -272,8 +273,8 @@ class WrapTests(unittest.TestCase):
"""
def setUp(self):
self.nl = NeighborList([1, 2, 3, 4, 5], default=3,
mode=NeighborList.Modes.wrap)
self.nl = usertypes.NeighborList(
[1, 2, 3, 4, 5], default=3, mode=usertypes.NeighborList.Modes.wrap)
def test_first(self):
"""Test ouf of bounds previtem()."""
@ -299,8 +300,9 @@ class RaiseTests(unittest.TestCase):
"""
def setUp(self):
self.nl = NeighborList([1, 2, 3, 4, 5], default=3,
mode=NeighborList.Modes.exception)
self.nl = usertypes.NeighborList(
[1, 2, 3, 4, 5], default=3,
mode=usertypes.NeighborList.Modes.exception)
def test_first(self):
"""Test ouf of bounds previtem()."""
@ -328,7 +330,7 @@ class SnapInTests(unittest.TestCase):
"""
def setUp(self):
self.nl = NeighborList([20, 9, 1, 5])
self.nl = usertypes.NeighborList([20, 9, 1, 5])
def test_bigger(self):
"""Test fuzzyval with snapping to a bigger value."""

View File

@ -21,15 +21,12 @@
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject
import qutebrowser.config.config as config
import qutebrowser.config.configdata as configdata
import qutebrowser.commands.utils as cmdutils
from qutebrowser.config import config, configdata
from qutebrowser.commands import utils as cmdutils
from qutebrowser.utils import usertypes
from qutebrowser.utils.log import completion as logger
from qutebrowser.models import completion as models
from qutebrowser.models.completionfilter import CompletionFilterModel as CFM
from qutebrowser.models.completion import (
CommandCompletionModel, SettingSectionCompletionModel,
SettingOptionCompletionModel, SettingValueCompletionModel)
from qutebrowser.utils.usertypes import Completion
class Completer(QObject):
@ -58,31 +55,32 @@ class Completer(QObject):
self.ignore_change = False
self._models = {
Completion.option: {},
Completion.value: {},
usertypes.Completion.option: {},
usertypes.Completion.value: {},
}
self._init_command_completion()
self._init_setting_completions()
def _init_command_completion(self):
"""Initialize the command completion model."""
self._models[Completion.command] = CFM(
CommandCompletionModel(self), self)
self._models[usertypes.Completion.command] = CFM(
models.CommandCompletionModel(self), self)
def _init_setting_completions(self):
"""Initialize setting completion models."""
self._models[Completion.section] = CFM(
SettingSectionCompletionModel(self), self)
self._models[Completion.option] = {}
self._models[Completion.value] = {}
self._models[usertypes.Completion.section] = CFM(
models.SettingSectionCompletionModel(self), self)
self._models[usertypes.Completion.option] = {}
self._models[usertypes.Completion.value] = {}
for sectname in configdata.DATA:
model = SettingOptionCompletionModel(sectname, self)
self._models[Completion.option][sectname] = CFM(model, self)
model = models.SettingOptionCompletionModel(sectname, self)
self._models[usertypes.Completion.option][sectname] = CFM(
model, self)
config.instance().changed.connect(model.on_config_changed)
self._models[Completion.value][sectname] = {}
self._models[usertypes.Completion.value][sectname] = {}
for opt in configdata.DATA[sectname].keys():
model = SettingValueCompletionModel(sectname, opt, self)
self._models[Completion.value][sectname][opt] = CFM(
model = models.SettingValueCompletionModel(sectname, opt, self)
self._models[usertypes.Completion.value][sectname][opt] = CFM(
model, self)
config.instance().changed.connect(model.on_config_changed)
@ -95,7 +93,7 @@ class Completer(QObject):
"""
if cursor_part == 0:
# '|' or 'set|'
return self._models[Completion.command]
return self._models[usertypes.Completion.command]
# delegate completion to command
try:
completions = cmdutils.cmd_dict[parts[0]].completion
@ -115,10 +113,10 @@ class Completer(QObject):
return None
dbg_completions[idx] = '*' + dbg_completions[idx] + '*'
logger.debug("completions: {}".format(', '.join(dbg_completions)))
if completion == Completion.option:
if completion == usertypes.Completion.option:
section = parts[cursor_part - 1]
model = self._models[completion].get(section)
elif completion == Completion.value:
elif completion == usertypes.Completion.value:
section = parts[cursor_part - 2]
option = parts[cursor_part - 1]
try:

View File

@ -23,13 +23,13 @@ import re
import pdb
import sys
import types
from functools import wraps
import functools
from PyQt5.QtCore import pyqtRemoveInputHook, QEvent, QCoreApplication
from qutebrowser.utils.misc import elide, compact_text
from qutebrowser.utils import misc as utils
from qutebrowser.utils.log import misc as logger
import qutebrowser.commands.utils as cmdutils
from qutebrowser.commands import utils as cmdutils
@cmdutils.register(debug=True, name='debug-set-trace')
@ -89,7 +89,7 @@ def log_events(klass):
"""Class decorator to log Qt events."""
old_event = klass.event
@wraps(old_event)
@functools.wraps(old_event)
def new_event(self, e, *args, **kwargs):
"""Wrapper for event() which logs events."""
logger.debug("Event in {}: {}".format(klass.__name__,
@ -115,7 +115,7 @@ def trace_lines(do_trace):
if sys is not None:
loc = '{}:{}'.format(frame.f_code.co_filename, frame.f_lineno)
if arg is not None:
arg = compact_text(str(arg), 200)
arg = utils.compact_text(str(arg), 200)
else:
arg = ''
print("{:11} {:80} {}".format(event, loc, arg), file=sys.stderr)
@ -228,5 +228,6 @@ def dbg_signal(sig, args):
Return:
A human-readable string representation of signal/args.
"""
argstr = ', '.join([elide(str(a).replace('\n', ' '), 20) for a in args])
argstr = ', '.join([utils.elide(str(a).replace('\n', ' '), 20)
for a in args])
return '{}({})'.format(signal_name(sig), argstr)

View File

@ -26,9 +26,9 @@ import faulthandler
import traceback
import signal
try:
from tkinter import Tk, messagebox # pylint: disable=import-error
import tkinter # pylint: disable=import-error
except ImportError:
Tk = None
tkinter = None
def _missing_str(name, debian=None, arch=None, windows=None, pip=None):
@ -186,10 +186,10 @@ def check_pyqt_core():
text = text.replace('<b>', '')
text = text.replace('</b>', '')
text = text.replace('<br />', '\n')
if Tk:
root = Tk()
if tkinter:
root = tkinter.Tk()
root.withdraw()
messagebox.showerror("qutebrowser: Fatal error!", text)
tkinter.messagebox.showerror("qutebrowser: Fatal error!", text)
else:
print(text, file=sys.stderr)
if '--debug' in sys.argv:

View File

@ -20,12 +20,12 @@
"""Launcher for an external editor."""
import os
from tempfile import mkstemp
import tempfile
from PyQt5.QtCore import pyqtSignal, QProcess, QObject
import qutebrowser.config.config as config
import qutebrowser.utils.message as message
from qutebrowser.config import config
from qutebrowser.utils import message
from qutebrowser.utils.log import procs as logger
@ -109,7 +109,7 @@ class ExternalEditor(QObject):
if self.text is not None:
raise ValueError("Already editing a file!")
self.text = text
self.oshandle, self.filename = mkstemp(text=True)
self.oshandle, self.filename = tempfile.mkstemp(text=True)
if text:
encoding = config.get('general', 'editor-encoding')
with open(self.filename, 'w', encoding=encoding) as f:

View File

@ -21,7 +21,7 @@
import os.path
import qutebrowser.utils.rfc6266 as rfc6266
from qutebrowser.utils import rfc6266
from qutebrowser.utils.log import misc as logger
from PyQt5.QtNetwork import QNetworkRequest

View File

@ -24,9 +24,8 @@ import os
import sys
import html as pyhtml
import logging
from contextlib import contextmanager
from logging import getLogger
from collections import deque
import contextlib
import collections
from PyQt5.QtCore import (QtDebugMsg, QtWarningMsg, QtCriticalMsg, QtFatalMsg,
qInstallMessageHandler)
@ -38,9 +37,9 @@ except ImportError:
colorama = None
try:
# pylint: disable=import-error
from colorlog import ColoredFormatter
import colorlog
except ImportError:
ColoredFormatter = None
colorlog = None
else:
# colorlog calls colorama.init() which we don't want, also it breaks our
# sys.stdout/sys.stderr if they are None. Bugreports:
@ -81,25 +80,25 @@ LOG_COLORS = {
# The different loggers used.
statusbar = getLogger('statusbar')
completion = getLogger('completion')
destroy = getLogger('destroy')
modes = getLogger('modes')
webview = getLogger('webview')
mouse = getLogger('mouse')
misc = getLogger('misc')
url = getLogger('url')
procs = getLogger('procs')
commands = getLogger('commands')
init = getLogger('init')
signals = getLogger('signals')
hints = getLogger('hints')
keyboard = getLogger('keyboard')
downloads = getLogger('downloads')
js = getLogger('js') # Javascript console messages
qt = getLogger('qt') # Warnings produced by Qt
style = getLogger('style')
rfc6266 = getLogger('rfc6266')
statusbar = logging.getLogger('statusbar')
completion = logging.getLogger('completion')
destroy = logging.getLogger('destroy')
modes = logging.getLogger('modes')
webview = logging.getLogger('webview')
mouse = logging.getLogger('mouse')
misc = logging.getLogger('misc')
url = logging.getLogger('url')
procs = logging.getLogger('procs')
commands = logging.getLogger('commands')
init = logging.getLogger('init')
signals = logging.getLogger('signals')
hints = logging.getLogger('hints')
keyboard = logging.getLogger('keyboard')
downloads = logging.getLogger('downloads')
js = logging.getLogger('js') # Javascript console messages
qt = logging.getLogger('qt') # Warnings produced by Qt
style = logging.getLogger('style')
rfc6266 = logging.getLogger('rfc6266')
ram_handler = None
@ -114,7 +113,7 @@ def init_log(args):
raise ValueError("Invalid log level: {}".format(args.loglevel))
console, ram = _init_handlers(numeric_level, args.color, args.loglines)
root = getLogger()
root = logging.getLogger()
if console is not None:
if args.logfilter is not None:
console.addFilter(LogFilter(args.logfilter.split(',')))
@ -126,7 +125,7 @@ def init_log(args):
qInstallMessageHandler(qt_message_handler)
@contextmanager
@contextlib.contextmanager
def disable_qt_msghandler():
"""Contextmanager which temporarely disables the Qt message handler."""
old_handler = qInstallMessageHandler(None)
@ -191,10 +190,10 @@ def _init_formatters(level, color):
if sys.stderr is None:
return None, ram_formatter, html_formatter, False
use_colorama = False
if (ColoredFormatter is not None and (os.name == 'posix' or colorama) and
if (colorlog is not None and (os.name == 'posix' or colorama) and
sys.stderr.isatty() and color):
console_formatter = ColoredFormatter(console_fmt_colored, DATEFMT,
log_colors=LOG_COLORS)
console_formatter = colorlog.ColoredFormatter(
console_fmt_colored, DATEFMT, log_colors=LOG_COLORS)
if colorama:
use_colorama = True
else:
@ -310,9 +309,9 @@ class RAMHandler(logging.Handler):
super().__init__()
self.html_formatter = None
if capacity != -1:
self.data = deque(maxlen=capacity)
self.data = collections.deque(maxlen=capacity)
else:
self.data = deque()
self.data = collections.deque()
def emit(self, record):
self.data.append(record)

View File

@ -21,7 +21,7 @@
from PyQt5.QtCore import pyqtSignal, QCoreApplication, QObject, QTimer
from qutebrowser.utils.usertypes import PromptMode, Question
from qutebrowser.utils import usertypes
from qutebrowser.utils.log import misc as logger
@ -64,7 +64,7 @@ def ask(message, mode, default=None):
Return:
The answer the user gave or None if the prompt was cancelled.
"""
q = Question()
q = usertypes.Question()
q.text = message
q.mode = mode
q.default = default
@ -75,9 +75,9 @@ def ask(message, mode, default=None):
def alert(message):
"""Display an alert which needs to be confirmed."""
q = Question()
q = usertypes.Question()
q.text = message
q.mode = PromptMode.alert
q.mode = usertypes.PromptMode.alert
instance().ask(q, blocking=True)
q.deleteLater()
@ -91,10 +91,10 @@ def ask_async(message, mode, handler, default=None):
handler: The function to get called with the answer as argument.
default: The default value to display.
"""
if not isinstance(mode, PromptMode):
if not isinstance(mode, usertypes.PromptMode):
raise TypeError("Mode {} is no PromptMode member!".format(mode))
bridge = instance()
q = Question(bridge)
q = usertypes.Question(bridge)
q.text = message
q.mode = mode
q.default = default
@ -113,9 +113,9 @@ def confirm_async(message, yes_action, no_action=None, default=None):
default: True/False to set a default value, or None.
"""
bridge = instance()
q = Question(bridge)
q = usertypes.Question(bridge)
q.text = message
q.mode = PromptMode.yesno
q.mode = usertypes.PromptMode.yesno
q.default = default
q.answered_yes.connect(yes_action)
if no_action is not None:
@ -152,7 +152,7 @@ class MessageBridge(QObject):
s_info = pyqtSignal(str, bool)
s_set_text = pyqtSignal(str)
s_set_cmd_text = pyqtSignal(str)
s_question = pyqtSignal(Question, bool)
s_question = pyqtSignal(usertypes.Question, bool)
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)

View File

@ -25,17 +25,17 @@ import sys
import shlex
import os.path
import urllib.request
from urllib.parse import urljoin, urlencode
from collections import OrderedDict
from functools import reduce
from contextlib import contextmanager
import urllib.parse
import collections
import functools
import contextlib
from PyQt5.QtCore import QCoreApplication, QStandardPaths, Qt
from PyQt5.QtGui import QKeySequence, QColor
from pkg_resources import resource_string
import pkg_resources
import qutebrowser
from qutebrowser.utils.qt import qt_version_check, qt_ensure_valid
from qutebrowser.utils import qt as qtutils
def elide(text, length):
@ -81,7 +81,8 @@ def read_file(filename):
with open(fn, 'r', encoding='utf-8') as f:
return f.read()
else:
return resource_string(qutebrowser.__name__, filename).decode('UTF-8')
data = pkg_resources.resource_string(qutebrowser.__name__, filename)
return data.decode('UTF-8')
def dotted_getattr(obj, path):
@ -94,7 +95,7 @@ def dotted_getattr(obj, path):
Return:
The object at path.
"""
return reduce(getattr, path.split('.'), obj)
return functools.reduce(getattr, path.split('.'), obj)
def safe_shlex_split(s):
@ -134,8 +135,8 @@ def pastebin(text):
'title': "qutebrowser crash",
'name': "qutebrowser",
}
encoded_data = urlencode(data).encode('utf-8')
create_url = urljoin(api_url, 'create')
encoded_data = urllib.parse.urlencode(data).encode('utf-8')
create_url = urllib.parse.urljoin(api_url, 'create')
headers = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
}
@ -189,7 +190,7 @@ def actute_warning():
return
# Qt >= 5.3 doesn't seem to be affected
try:
if qt_version_check('5.3.0'):
if qtutils.qt_version_check('5.3.0'):
return
except ValueError:
pass
@ -246,8 +247,8 @@ def interpolate_color(start, end, percent, colorspace=QColor.Rgb):
Raise:
ValueError if invalid parameters are passed.
"""
qt_ensure_valid(start)
qt_ensure_valid(end)
qtutils.qt_ensure_valid(start)
qtutils.qt_ensure_valid(end)
out = QColor()
if colorspace == QColor.Rgb:
a_c1, a_c2, a_c3, _alpha = start.getRgb()
@ -270,7 +271,7 @@ def interpolate_color(start, end, percent, colorspace=QColor.Rgb):
else:
raise ValueError("Invalid colorspace!")
out = out.convertTo(start.spec())
qt_ensure_valid(out)
qtutils.qt_ensure_valid(out)
return out
@ -400,7 +401,7 @@ def keyevent_to_string(e):
A name of the key (combination) as a string or
None if only modifiers are pressed..
"""
modmask2str = OrderedDict([
modmask2str = collections.OrderedDict([
(Qt.ControlModifier, 'Ctrl'),
(Qt.AltModifier, 'Alt'),
(Qt.MetaModifier, 'Meta'),
@ -460,7 +461,7 @@ class FakeIOStream(io.TextIOBase):
return super().isatty()
@contextmanager
@contextlib.contextmanager
def fake_io(write_func):
"""Run code with stdout and stderr replaced by FakeIOStreams.
@ -482,7 +483,7 @@ def fake_io(write_func):
sys.stderr = old_stderr
@contextmanager
@contextlib.contextmanager
def disabled_excepthook():
"""Run code with the exception hook temporarely disabled."""
old_excepthook = sys.excepthook

View File

@ -21,8 +21,8 @@
from PyQt5.QtWidgets import QApplication, QLineEdit
import qutebrowser.commands.utils as cmd
from qutebrowser.utils.usertypes import KeyMode
from qutebrowser.commands import utils as cmdutils
from qutebrowser.utils import usertypes as typ
class ReadlineBridge:
@ -45,8 +45,8 @@ class ReadlineBridge:
else:
return None
@cmd.register(instance='rl_bridge', hide=True,
modes=[KeyMode.command, KeyMode.prompt])
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
def rl_backward_char(self):
"""Move back a character.
@ -56,8 +56,8 @@ class ReadlineBridge:
return
self.widget.cursorBackward(False)
@cmd.register(instance='rl_bridge', hide=True,
modes=[KeyMode.command, KeyMode.prompt])
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
def rl_forward_char(self):
"""Move forward a character.
@ -67,8 +67,8 @@ class ReadlineBridge:
return
self.widget.cursorForward(False)
@cmd.register(instance='rl_bridge', hide=True,
modes=[KeyMode.command, KeyMode.prompt])
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
def rl_backward_word(self):
"""Move back to the start of the current or previous word.
@ -78,8 +78,8 @@ class ReadlineBridge:
return
self.widget.cursorWordBackward(False)
@cmd.register(instance='rl_bridge', hide=True,
modes=[KeyMode.command, KeyMode.prompt])
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
def rl_forward_word(self):
"""Move forward to the end of the next word.
@ -89,8 +89,8 @@ class ReadlineBridge:
return
self.widget.cursorWordForward(False)
@cmd.register(instance='rl_bridge', hide=True,
modes=[KeyMode.command, KeyMode.prompt])
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
def rl_beginning_of_line(self):
"""Move to the start of the line.
@ -100,8 +100,8 @@ class ReadlineBridge:
return
self.widget.home(False)
@cmd.register(instance='rl_bridge', hide=True,
modes=[KeyMode.command, KeyMode.prompt])
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
def rl_end_of_line(self):
"""Move to the end of the line.
@ -111,8 +111,8 @@ class ReadlineBridge:
return
self.widget.end(False)
@cmd.register(instance='rl_bridge', hide=True,
modes=[KeyMode.command, KeyMode.prompt])
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
def rl_unix_line_discard(self):
"""Remove chars backward from the cursor to the beginning of the line.
@ -124,8 +124,8 @@ class ReadlineBridge:
self.deleted[self.widget] = self.widget.selectedText()
self.widget.del_()
@cmd.register(instance='rl_bridge', hide=True,
modes=[KeyMode.command, KeyMode.prompt])
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
def rl_kill_line(self):
"""Remove chars from the cursor to the end of the line.
@ -137,8 +137,8 @@ class ReadlineBridge:
self.deleted[self.widget] = self.widget.selectedText()
self.widget.del_()
@cmd.register(instance='rl_bridge', hide=True,
modes=[KeyMode.command, KeyMode.prompt])
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
def rl_unix_word_rubout(self):
"""Remove chars from the cursor to the beginning of the word.
@ -150,8 +150,8 @@ class ReadlineBridge:
self.deleted[self.widget] = self.widget.selectedText()
self.widget.del_()
@cmd.register(instance='rl_bridge', hide=True,
modes=[KeyMode.command, KeyMode.prompt])
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
def rl_kill_word(self):
"""Remove chars from the cursor to the end of the current word.
@ -163,8 +163,8 @@ class ReadlineBridge:
self.deleted[self.widget] = self.widget.selectedText()
self.widget.del_()
@cmd.register(instance='rl_bridge', hide=True,
modes=[KeyMode.command, KeyMode.prompt])
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
def rl_yank(self):
"""Paste the most recently deleted text.
@ -174,8 +174,8 @@ class ReadlineBridge:
return
self.widget.insert(self.deleted[self.widget])
@cmd.register(instance='rl_bridge', hide=True,
modes=[KeyMode.command, KeyMode.prompt])
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
def rl_delete_char(self):
"""Delete the character after the cursor.
@ -185,8 +185,8 @@ class ReadlineBridge:
return
self.widget.del_()
@cmd.register(instance='rl_bridge', hide=True,
modes=[KeyMode.command, KeyMode.prompt])
@cmdutils.register(instance='rl_bridge', hide=True,
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
def rl_backward_delete_char(self):
"""Delete the character before the cursor.

View File

@ -19,7 +19,7 @@
"""pyPEG parsing for the RFC 6266 (Content-Disposition) header. """
from collections import namedtuple
import collections
import urllib.parse
import string
import re
@ -209,7 +209,7 @@ class ContentDispositionValue:
peg.optional(';'))
LangTagged = namedtuple('LangTagged', 'string langtag')
LangTagged = collections.namedtuple('LangTagged', 'string langtag')
class DuplicateParamError(Exception):

View File

@ -26,9 +26,9 @@ import urllib.parse
from PyQt5.QtCore import QUrl
from PyQt5.QtNetwork import QHostInfo
import qutebrowser.config.config as config
from qutebrowser.config import config
from qutebrowser.utils import qt as qtutils
from qutebrowser.utils.log import url as logger
from qutebrowser.utils.misc import qt_ensure_valid
# FIXME: we probably could raise some exceptions on invalid URLs
@ -65,7 +65,7 @@ def _get_search_url(txt):
if not term:
raise FuzzyUrlError("No search term given")
url = QUrl.fromUserInput(template.format(urllib.parse.quote(term)))
qt_ensure_valid(url)
qtutils.qt_ensure_valid(url)
return url
@ -143,7 +143,7 @@ def fuzzy_url(urlstr):
url = QUrl.fromUserInput(stripped)
logger.debug("Converting fuzzy term {} to URL -> {}".format(
urlstr, url.toDisplayString()))
qt_ensure_valid(url)
qtutils.qt_ensure_valid(url)
return url

View File

@ -29,8 +29,8 @@ import enum as pyenum
from PyQt5.QtCore import pyqtSignal, QObject, QTimer
from qutebrowser.utils import qt as qtutils
from qutebrowser.utils.log import misc as logger
from qutebrowser.utils.qt import check_overflow
_UNSET = object()
@ -372,13 +372,13 @@ class Timer(QTimer):
def setInterval(self, msec):
"""Extend setInterval to check for overflows."""
check_overflow(msec, 'int')
qtutils.check_overflow(msec, 'int')
super().setInterval(msec)
def start(self, msec=None):
"""Extend start to check for overflows."""
if msec is not None:
check_overflow(msec, 'int')
qtutils.check_overflow(msec, 'int')
super().start(msec)
else:
super().start()

View File

@ -21,10 +21,10 @@
from functools import partial
import qutebrowser.commands.utils as cmdutils
from qutebrowser.utils.usertypes import Timer
from qutebrowser.commands.exceptions import CommandError
from qutebrowser.commands.runners import CommandRunner
from qutebrowser.utils import usertypes
from qutebrowser.commands import runners
from qutebrowser.commands import utils as cmdutils
from qutebrowser.commands import exceptions as cmdexc
_timers = []
@ -34,7 +34,7 @@ _commandrunner = None
def init():
"""Initialize the global _commandrunner."""
global _commandrunner
_commandrunner = CommandRunner()
_commandrunner = runners.CommandRunner()
@cmdutils.register(nargs=(2, None))
@ -46,15 +46,15 @@ def later(ms, *command):
command: The command/args to run.
"""
ms = int(ms)
timer = Timer(name='later')
timer = usertypes.Timer(name='later')
timer.setSingleShot(True)
if ms < 0:
raise CommandError("I can't run something in the past!")
raise cmdexc.CommandError("I can't run something in the past!")
try:
timer.setInterval(ms)
except OverflowError:
raise CommandError("Numeric argument is too large for internal int "
"representation.")
raise cmdexc.CommandError("Numeric argument is too large for internal "
"int representation.")
_timers.append(timer)
cmdline = ' '.join(command)
timer.timeout.connect(partial(_commandrunner.run_safely, cmdline))

View File

@ -29,7 +29,7 @@ from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, qVersion
from PyQt5.QtWebKit import qWebKitVersion
import qutebrowser
from qutebrowser.utils.misc import read_file
from qutebrowser.utils import misc as utils
from qutebrowser.utils.log import misc as logger
@ -91,7 +91,7 @@ def _git_str():
return commit
# If that fails, check the git-commit-id file.
try:
return read_file('git-commit-id')
return utils.read_file('git-commit-id')
except (FileNotFoundError, ImportError):
return None

View File

@ -30,13 +30,13 @@ Module attributes:
from PyQt5.QtCore import QRect, QUrl
from PyQt5.QtWebKit import QWebElement
import qutebrowser.utils.log as log
import qutebrowser.config.config as config
from qutebrowser.utils.usertypes import enum
from qutebrowser.utils.misc import compact_text
from qutebrowser.config import config
from qutebrowser.utils import log, usertypes
from qutebrowser.utils import misc as utils
Group = enum('Group', 'all', 'links', 'images', 'url', 'prevnext', 'focus')
Group = usertypes.enum('Group', 'all', 'links', 'images', 'url', 'prevnext',
'focus')
SELECTORS = {
@ -284,4 +284,4 @@ def focus_elem(frame):
def debug_text(elem):
"""Get a text based on an element suitable for debug output."""
return compact_text(elem.toOuterXml(), 500)
return utils.compact_text(elem.toOuterXml(), 500)

View File

@ -26,13 +26,11 @@ subclasses to provide completions.
from PyQt5.QtWidgets import QStyle, QTreeView, QSizePolicy
from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QItemSelectionModel
import qutebrowser.config.config as config
import qutebrowser.commands.utils as cmdutils
from qutebrowser.widgets.completiondelegate import CompletionItemDelegate
from qutebrowser.config.style import set_register_stylesheet
from qutebrowser.utils.completer import Completer
from qutebrowser.utils.qt import qt_ensure_valid
from qutebrowser.utils.usertypes import KeyMode
from qutebrowser.commands import utils as cmdutils
from qutebrowser.config import config, style
from qutebrowser.widgets import completiondelegate
from qutebrowser.utils import completer, usertypes
from qutebrowser.utils import qt as qtutils
class CompletionView(QTreeView):
@ -94,12 +92,12 @@ class CompletionView(QTreeView):
def __init__(self, parent=None):
super().__init__(parent)
self.completer = Completer(self)
self.completer = completer.Completer(self)
self.enabled = config.get('completion', 'show')
self._delegate = CompletionItemDelegate(self)
self._delegate = completiondelegate.CompletionItemDelegate(self)
self.setItemDelegate(self._delegate)
set_register_stylesheet(self)
style.set_register_stylesheet(self)
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)
self.setHeaderHidden(True)
self.setIndentation(0)
@ -169,7 +167,7 @@ class CompletionView(QTreeView):
# No completion running at the moment, ignore keypress
return
idx = self._next_idx(prev)
qt_ensure_valid(idx)
qtutils.qt_ensure_valid(idx)
self.selectionModel().setCurrentIndex(
idx, QItemSelectionModel.ClearAndSelect |
QItemSelectionModel.Rows)
@ -212,13 +210,13 @@ class CompletionView(QTreeView):
selmod.clearCurrentIndex()
@cmdutils.register(instance='mainwindow.completion', hide=True,
modes=[KeyMode.command])
modes=[usertypes.KeyMode.command])
def completion_item_prev(self):
"""Select the previous completion item."""
self._next_prev_item(prev=True)
@cmdutils.register(instance='mainwindow.completion', hide=True,
modes=[KeyMode.command])
modes=[usertypes.KeyMode.command])
def completion_item_next(self):
"""Select the next completion item."""
self._next_prev_item(prev=False)

View File

@ -28,10 +28,9 @@ from PyQt5.QtCore import QRectF, QSize, Qt
from PyQt5.QtGui import (QIcon, QPalette, QTextDocument, QTextOption,
QTextCursor, QAbstractTextDocumentLayout)
import qutebrowser.config.config as config
from qutebrowser.models.basecompletion import Role
from qutebrowser.config.style import get_stylesheet
from qutebrowser.utils.qt import qt_ensure_valid
from qutebrowser.config import config, style
from qutebrowser.models import basecompletion
from qutebrowser.utils import qt as qtutils
class CompletionItemDelegate(QStyledItemDelegate):
@ -99,12 +98,12 @@ class CompletionItemDelegate(QStyledItemDelegate):
text_rect_ = self._style.subElementRect(
self._style.SE_ItemViewItemText, self._opt, self._opt.widget)
qt_ensure_valid(text_rect_)
qtutils.qt_ensure_valid(text_rect_)
margin = self._style.pixelMetric(QStyle.PM_FocusFrameHMargin,
self._opt, self._opt.widget) + 1
# remove width padding
text_rect = text_rect_.adjusted(margin, 0, -margin, 0)
qt_ensure_valid(text_rect)
qtutils.qt_ensure_valid(text_rect)
# move text upwards a bit
if index.parent().isValid():
text_rect.adjust(0, -1, 0, -1)
@ -189,7 +188,7 @@ class CompletionItemDelegate(QStyledItemDelegate):
self._doc.setHtml('<b>{}</b>'.format(html.escape(self._opt.text)))
self._doc.setDefaultFont(self._opt.font)
self._doc.setDefaultTextOption(text_option)
self._doc.setDefaultStyleSheet(get_stylesheet("""
self._doc.setDefaultStyleSheet(style.get_stylesheet("""
.highlight {{
{color[completion.match.fg]}
}}
@ -197,7 +196,7 @@ class CompletionItemDelegate(QStyledItemDelegate):
self._doc.setDocumentMargin(2)
if index.column() == 0:
marks = index.data(Role.marks)
marks = index.data(basecompletion.Role.marks)
if marks is None:
return
for mark in marks:
@ -218,7 +217,7 @@ class CompletionItemDelegate(QStyledItemDelegate):
o.rect = self._style.subElementRect(
self._style.SE_ItemViewItemFocusRect, self._opt, self._opt.widget)
o.state |= QStyle.State_KeyboardFocusChange | QStyle.State_Item
qt_ensure_valid(o.rect)
qtutils.qt_ensure_valid(o.rect)
if state & QStyle.State_Enabled:
cg = QPalette.Normal
else:
@ -254,7 +253,7 @@ class CompletionItemDelegate(QStyledItemDelegate):
docsize = self._doc.size().toSize()
size = self._style.sizeFromContents(QStyle.CT_ItemViewItem, self._opt,
docsize, self._opt.widget)
qt_ensure_valid(size)
qtutils.qt_ensure_valid(size)
return size + QSize(10, 3)
def paint(self, painter, option, index):

View File

@ -20,19 +20,18 @@
"""Debugging console."""
import sys
from code import InteractiveInterpreter
import code
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt
from PyQt5.QtWidgets import QTextEdit, QWidget, QVBoxLayout, QApplication
import qutebrowser.config.config as config
from qutebrowser.models.cmdhistory import (History, HistoryEmptyError,
HistoryEndReachedError)
from qutebrowser.utils.misc import fake_io, disabled_excepthook
from qutebrowser.widgets.misc import CommandLineEdit
from qutebrowser.config import config
from qutebrowser.models import cmdhistory
from qutebrowser.utils import misc as utils
from qutebrowser.widgets import misc
class ConsoleLineEdit(CommandLineEdit):
class ConsoleLineEdit(misc.CommandLineEdit):
"""A QLineEdit which executes entered code and provides a history."""
@ -56,8 +55,8 @@ class ConsoleLineEdit(CommandLineEdit):
# console, not just the line edit.
'self': parent,
}
self._interpreter = InteractiveInterpreter(interpreter_locals)
self.history = History()
self._interpreter = code.InteractiveInterpreter(interpreter_locals)
self.history = cmdhistory.History()
self.returnPressed.connect(self.execute)
self.setText('')
@ -88,7 +87,7 @@ class ConsoleLineEdit(CommandLineEdit):
# same.
# - We disable our exception hook, so exceptions from the console get
# printed and don't ooen a crashdialog.
with fake_io(self.write.emit), disabled_excepthook():
with utils.fake_io(self.write.emit), utils.disabled_excepthook():
self._more = self._interpreter.runsource(source, '<console>')
self.set_prompt(self.curprompt)
if not self._more:
@ -101,7 +100,8 @@ class ConsoleLineEdit(CommandLineEdit):
item = self.history.start(self.text().strip())
else:
item = self.history.previtem()
except (HistoryEmptyError, HistoryEndReachedError):
except (cmdhistory.HistoryEmptyError,
cmdhistory.HistoryEndReachedError):
return
self.setText(item)
@ -111,7 +111,7 @@ class ConsoleLineEdit(CommandLineEdit):
return
try:
item = self.history.nextitem()
except HistoryEndReachedError:
except cmdhistory.HistoryEndReachedError:
return
self.setText(item)

View File

@ -21,17 +21,16 @@
import sys
import traceback
from urllib.error import URLError
from getpass import getuser
import urllib.error
import getpass
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtWidgets import (QDialog, QLabel, QTextEdit, QPushButton,
QVBoxLayout, QHBoxLayout)
import qutebrowser.config.config as config
import qutebrowser.utils.misc as utils
import qutebrowser.utils.log as logutils
from qutebrowser.utils.version import version
from qutebrowser.config import config
from qutebrowser.utils import version, log
from qutebrowser.utils import misc as utils
class _CrashDialog(QDialog):
@ -124,11 +123,11 @@ class _CrashDialog(QDialog):
]
try:
self._crash_info.append(("Contact info",
"User: {}".format(getuser())))
"User: {}".format(getpass.getuser())))
except Exception as e: # pylint: disable=broad-except
self._crash_info.append(("Contact info", "User: {}: {}".format(
e.__class__.__name__, e)))
self._crash_info.append(("Version info", version()))
self._crash_info.append(("Version info", version.version()))
try:
self._crash_info.append(("Config",
config.instance().dump_userconfig()))
@ -156,7 +155,7 @@ class _CrashDialog(QDialog):
"""Paste the crash info into the pastebin."""
try:
url = utils.pastebin(self._txt.toPlainText())
except (URLError, ValueError) as e:
except (urllib.error.URLError, ValueError) as e:
self._url.setText('Error while reporting: {}: {}'.format(
e.__class__.__name__, e))
return
@ -228,8 +227,7 @@ class ExceptionCrashDialog(_CrashDialog):
("Objects", self._objects),
]
try:
self._crash_info.append(("Debug log",
logutils.ram_handler.dump_log()))
self._crash_info.append(("Debug log", log.ram_handler.dump_log()))
except AttributeError as e:
self._crash_info.append(("Debug log", "{}: {}".format(
e.__class__.__name__, e)))
@ -245,8 +243,8 @@ class FatalCrashDialog(_CrashDialog):
_btn_pastebin: The pastebin button.
"""
def __init__(self, log, parent=None):
self._log = log
def __init__(self, text, parent=None):
self._log = text
self._btn_ok = None
self._btn_pastebin = None
super().__init__(parent)
@ -329,8 +327,7 @@ class ReportDialog(_CrashDialog):
("Objects", self._objects),
]
try:
self._crash_info.append(("Debug log",
logutils.ram_handler.dump_log()))
self._crash_info.append(("Debug log", log.ram_handler.dump_log()))
except AttributeError as e:
self._crash_info.append(("Debug log", "{}: {}".format(
e.__class__.__name__, e)))

View File

@ -22,9 +22,9 @@
from PyQt5.QtCore import pyqtSlot, QSize, Qt
from PyQt5.QtWidgets import QListView, QSizePolicy, QMenu
from qutebrowser.models.downloadmodel import DownloadModel, Role
from qutebrowser.config.style import set_register_stylesheet
from qutebrowser.utils.qt import qt_ensure_valid
from qutebrowser.models import downloadmodel
from qutebrowser.config import style
from qutebrowser.utils import qt as qtutils
class DownloadView(QListView):
@ -49,13 +49,13 @@ class DownloadView(QListView):
def __init__(self, parent=None):
super().__init__(parent)
set_register_stylesheet(self)
style.set_register_stylesheet(self)
self.setResizeMode(QListView.Adjust)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
self.setFlow(QListView.LeftToRight)
self._menu = None
self._model = DownloadModel(self)
self._model = downloadmodel.DownloadModel(self)
self._model.rowsInserted.connect(self.updateGeometry)
self._model.rowsRemoved.connect(self.updateGeometry)
self.setModel(self._model)
@ -73,7 +73,7 @@ class DownloadView(QListView):
index = self.indexAt(point)
if not index.isValid():
return
item = self.model().data(index, Role.item)
item = self.model().data(index, downloadmodel.Role.item)
self._menu = QMenu(self)
cancel = self._menu.addAction("Cancel")
cancel.triggered.connect(item.cancel)
@ -91,5 +91,5 @@ class DownloadView(QListView):
size = QSize(0, height + 2)
else:
size = QSize(0, 0)
qt_ensure_valid(size)
qtutils.qt_ensure_valid(size)
return size

View File

@ -20,21 +20,17 @@
"""The main window of qutebrowser."""
import binascii
from base64 import b64decode
import base64
from PyQt5.QtCore import pyqtSlot, QRect, QPoint, QCoreApplication, QTimer
from PyQt5.QtWidgets import QWidget, QVBoxLayout
import qutebrowser.commands.utils as cmdutils
import qutebrowser.config.config as config
import qutebrowser.utils.message as message
import qutebrowser.utils.log as log
from qutebrowser.widgets.statusbar.bar import StatusBar
from qutebrowser.widgets.tabbedbrowser import TabbedBrowser
from qutebrowser.widgets.completion import CompletionView
from qutebrowser.widgets.downloads import DownloadView
from qutebrowser.utils.usertypes import PromptMode
from qutebrowser.utils.qt import check_overflow
from qutebrowser.commands import utils as cmdutils
from qutebrowser.config import config
from qutebrowser.utils import message, log, usertypes
from qutebrowser.utils import qt as qtutils
from qutebrowser.widgets import tabbedbrowser, completion, downloads
from qutebrowser.widgets.statusbar import bar
class MainWindow(QWidget):
@ -57,9 +53,9 @@ class MainWindow(QWidget):
self.setWindowTitle('qutebrowser')
try:
stateconf = QCoreApplication.instance().stateconfig
base64 = stateconf['geometry']['mainwindow']
log.init.debug("Restoring mainwindow from {}".format(base64))
geom = b64decode(base64, validate=True)
data = stateconf['geometry']['mainwindow']
log.init.debug("Restoring mainwindow from {}".format(data))
geom = base64.b64decode(data, validate=True)
except (KeyError, binascii.Error) as e:
log.init.warning("Error while reading geometry: {}: {}".format(
e.__class__.__name__, e))
@ -81,17 +77,17 @@ class MainWindow(QWidget):
self._vbox.setContentsMargins(0, 0, 0, 0)
self._vbox.setSpacing(0)
self.downloadview = DownloadView()
self.downloadview = downloads.DownloadView()
self._vbox.addWidget(self.downloadview)
self.downloadview.show()
self.tabs = TabbedBrowser()
self.tabs = tabbedbrowser.TabbedBrowser()
self.tabs.title_changed.connect(self.setWindowTitle)
self._vbox.addWidget(self.tabs)
self.completion = CompletionView(self)
self.completion = completion.CompletionView(self)
self.status = StatusBar()
self.status = bar.StatusBar()
self._vbox.addWidget(self.status)
# When we're here the statusbar might not even really exist yet, so
@ -139,7 +135,7 @@ class MainWindow(QWidget):
# hpoint now would be the bottom-left edge of the widget if it was on
# the top of the main window.
topleft_y = self.height() - self.status.height() - height
topleft_y = check_overflow(topleft_y, 'int', fatal=False)
topleft_y = qtutils.check_overflow(topleft_y, 'int', fatal=False)
topleft = QPoint(0, topleft_y)
bottomright = self.status.geometry().topRight()
rect = QRect(topleft, bottomright)
@ -178,7 +174,8 @@ class MainWindow(QWidget):
else:
text = "Close {} {}?".format(
count, "tab" if count == 1 else "tabs")
confirmed = message.ask(text, PromptMode.yesno, default=True)
confirmed = message.ask(text, usertypes.PromptMode.yesno,
default=True)
if confirmed:
e.accept()
else:

View File

@ -23,7 +23,7 @@ from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtGui import QValidator
from qutebrowser.models.cmdhistory import History
from qutebrowser.models import cmdhistory
class MinimalLineEditMixin:
@ -55,7 +55,7 @@ class CommandLineEdit(QLineEdit):
def __init__(self, parent=None):
super().__init__(parent)
self.history = History()
self.history = cmdhistory.History()
self._validator = _CommandValidator(self)
self.setValidator(self._validator)
self.textEdited.connect(self.on_text_edited)

View File

@ -19,27 +19,22 @@
"""The main statusbar widget."""
from collections import deque
from datetime import datetime
import collections
import datetime
from PyQt5.QtCore import pyqtSignal, pyqtSlot, pyqtProperty, Qt
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QStackedLayout, QSizePolicy
import qutebrowser.keyinput.modeman as modeman
import qutebrowser.config.config as config
from qutebrowser.keyinput import modeman
from qutebrowser.config import config, style
from qutebrowser.utils import usertypes
from qutebrowser.utils.log import statusbar as logger
from qutebrowser.widgets.statusbar.command import Command
from qutebrowser.widgets.statusbar.progress import Progress
from qutebrowser.widgets.statusbar.text import Text
from qutebrowser.widgets.statusbar.keystring import KeyString
from qutebrowser.widgets.statusbar.percentage import Percentage
from qutebrowser.widgets.statusbar.url import UrlText
from qutebrowser.widgets.statusbar.prompt import Prompt
from qutebrowser.config.style import set_register_stylesheet, get_stylesheet
from qutebrowser.utils.usertypes import Timer, KeyMode, enum
from qutebrowser.widgets.statusbar import (command, progress, keystring,
percentage, url, prompt)
from qutebrowser.widgets.statusbar import text as textwidget
PreviousWidget = enum('PreviousWidget', 'none', 'prompt', 'command')
PreviousWidget = usertypes.enum('PreviousWidget', 'none', 'prompt', 'command')
class StatusBar(QWidget):
@ -128,7 +123,7 @@ class StatusBar(QWidget):
super().__init__(parent)
self.setObjectName(self.__class__.__name__)
self.setAttribute(Qt.WA_StyledBackground)
set_register_stylesheet(self)
style.set_register_stylesheet(self)
self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
@ -143,18 +138,18 @@ class StatusBar(QWidget):
self._hbox.addLayout(self._stack)
self._stack.setContentsMargins(0, 0, 0, 0)
self.cmd = Command()
self.cmd = command.Command()
self._stack.addWidget(self.cmd)
self.txt = Text()
self.txt = textwidget.Text()
self._stack.addWidget(self.txt)
self._timer_was_active = False
self._text_queue = deque()
self._text_pop_timer = Timer(self, 'statusbar_text_pop')
self._text_queue = collections.deque()
self._text_pop_timer = usertypes.Timer(self, 'statusbar_text_pop')
self._text_pop_timer.setInterval(config.get('ui', 'message-timeout'))
self._text_pop_timer.timeout.connect(self._pop_text)
self.prompt = Prompt()
self.prompt = prompt.Prompt()
self._stack.addWidget(self.prompt)
self._previous_widget = PreviousWidget.none
@ -165,19 +160,19 @@ class StatusBar(QWidget):
self.prompt.hide_prompt.connect(self._hide_prompt_widget)
self._hide_prompt_widget()
self.keystring = KeyString()
self.keystring = keystring.KeyString()
self._hbox.addWidget(self.keystring)
self.url = UrlText()
self.url = url.UrlText()
self._hbox.addWidget(self.url)
self.percentage = Percentage()
self.percentage = percentage.Percentage()
self._hbox.addWidget(self.percentage)
# We add a parent to Progress here because it calls self.show() based
# on some signals, and if that happens before it's added to the layout,
# it will quickly blink up as independent window.
self.prog = Progress(self)
self.prog = progress.Progress(self)
self._hbox.addWidget(self.prog)
def __repr__(self):
@ -198,7 +193,7 @@ class StatusBar(QWidget):
"""
logger.debug("Setting error to {}".format(val))
self._error = val
self.setStyleSheet(get_stylesheet(self.STYLESHEET))
self.setStyleSheet(style.get_stylesheet(self.STYLESHEET))
if val:
# If we got an error while command/prompt was shown, raise the text
# widget.
@ -219,7 +214,7 @@ class StatusBar(QWidget):
"""
logger.debug("Setting prompt_active to {}".format(val))
self._prompt_active = val
self.setStyleSheet(get_stylesheet(self.STYLESHEET))
self.setStyleSheet(style.get_stylesheet(self.STYLESHEET))
@pyqtProperty(bool)
def insert_active(self):
@ -236,7 +231,7 @@ class StatusBar(QWidget):
"""
logger.debug("Setting insert_active to {}".format(val))
self._insert_active = val
self.setStyleSheet(get_stylesheet(self.STYLESHEET))
self.setStyleSheet(style.get_stylesheet(self.STYLESHEET))
def _pop_text(self):
"""Display a text in the statusbar and pop it from _text_queue."""
@ -316,7 +311,7 @@ class StatusBar(QWidget):
"""
# FIXME probably using a QTime here would be easier.
logger.debug("Displaying text: {} (error={})".format(text, error))
now = datetime.now()
now = datetime.datetime.now()
mindelta = config.get('ui', 'message-timeout')
delta = (None if self._last_text_time is None
else now - self._last_text_time)
@ -379,20 +374,20 @@ class StatusBar(QWidget):
"""Set a normal (persistent) text in the status bar."""
self.txt.normaltext = val
@pyqtSlot(KeyMode)
@pyqtSlot(usertypes.KeyMode)
def on_mode_entered(self, mode):
"""Mark certain modes in the commandline."""
if mode in modeman.instance().passthrough:
self.txt.normaltext = "-- {} MODE --".format(mode.name.upper())
if mode == KeyMode.insert:
if mode == usertypes.KeyMode.insert:
self.insert_active = True
@pyqtSlot(KeyMode)
@pyqtSlot(usertypes.KeyMode)
def on_mode_left(self, mode):
"""Clear marked mode."""
if mode in modeman.instance().passthrough:
self.txt.normaltext = ""
if mode == KeyMode.insert:
if mode == usertypes.KeyMode.insert:
self.insert_active = False
@pyqtSlot(str, str)

View File

@ -22,19 +22,17 @@
from PyQt5.QtCore import pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QSizePolicy, QApplication
import qutebrowser.keyinput.modeman as modeman
import qutebrowser.commands.utils as cmdutils
from qutebrowser.widgets.misc import MinimalLineEditMixin, CommandLineEdit
from qutebrowser.commands.runners import CommandRunner
from qutebrowser.keyinput.modeparsers import STARTCHARS
from qutebrowser.keyinput import modeman, modeparsers
from qutebrowser.commands import runners
from qutebrowser.commands import utils as cmdutils
from qutebrowser.commands import exceptions as cmdexc
from qutebrowser.widgets import misc
from qutebrowser.models import cmdhistory
from qutebrowser.utils import usertypes
from qutebrowser.utils.log import completion as logger
from qutebrowser.models.cmdhistory import (HistoryEmptyError,
HistoryEndReachedError)
from qutebrowser.commands.exceptions import CommandError
from qutebrowser.utils.usertypes import KeyMode
class Command(MinimalLineEditMixin, CommandLineEdit):
class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
"""The commandline part of the statusbar.
@ -76,8 +74,8 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
# for a possible fix.
def __init__(self, parent=None):
CommandLineEdit.__init__(self, parent)
MinimalLineEditMixin.__init__(self)
misc.CommandLineEdit.__init__(self, parent)
misc.MinimalLineEditMixin.__init__(self)
self.cursor_part = 0
self.history.history = QApplication.instance().cmd_history.data
self._empty_item_idx = None
@ -92,7 +90,7 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
text = self.text()
if not text:
return ''
elif text[0] in STARTCHARS:
elif text[0] in modeparsers.STARTCHARS:
return text[0]
else:
return ''
@ -109,7 +107,7 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
# Text is only whitespace so we treat this as a single element with
# the whitespace.
return [text]
runner = CommandRunner()
runner = runners.CommandRunner()
parts = runner.parse(text, fallback=True, alias_no_args=False)
if self._empty_item_idx is not None:
logger.debug("Empty element queued at {}, inserting.".format(
@ -179,8 +177,9 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
strings: A list of strings to set.
"""
text = ' '.join(strings)
if not text[0] in STARTCHARS:
raise CommandError("Invalid command text '{}'.".format(text))
if not text[0] in modeparsers.STARTCHARS:
raise cmdexc.CommandError(
"Invalid command text '{}'.".format(text))
self.set_cmd_text(text)
@pyqtSlot(str, bool)
@ -215,7 +214,7 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
self.show_cmd.emit()
@cmdutils.register(instance='mainwindow.status.cmd', hide=True,
modes=[KeyMode.command])
modes=[usertypes.KeyMode.command])
def command_history_prev(self):
"""Go back in the commandline history."""
try:
@ -223,26 +222,27 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
item = self.history.start(self.text().strip())
else:
item = self.history.previtem()
except (HistoryEmptyError, HistoryEndReachedError):
except (cmdhistory.HistoryEmptyError,
cmdhistory.HistoryEndReachedError):
return
if item:
self.set_cmd_text(item)
@cmdutils.register(instance='mainwindow.status.cmd', hide=True,
modes=[KeyMode.command])
modes=[usertypes.KeyMode.command])
def command_history_next(self):
"""Go forward in the commandline history."""
if not self.history.browsing:
return
try:
item = self.history.nextitem()
except HistoryEndReachedError:
except cmdhistory.HistoryEndReachedError:
return
if item:
self.set_cmd_text(item)
@cmdutils.register(instance='mainwindow.status.cmd', hide=True,
modes=[KeyMode.command])
modes=[usertypes.KeyMode.command])
def command_accept(self):
"""Execute the command currently in the commandline.
@ -258,7 +258,7 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
}
text = self.text()
self.history.append(text)
modeman.leave(KeyMode.command, 'cmd accept')
modeman.leave(usertypes.KeyMode.command, 'cmd accept')
if text[0] in signals:
signals[text[0]].emit(text.lstrip(text[0]))
@ -271,7 +271,7 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
# here, but that's already done for us by cursorPositionChanged
# anyways, so we don't need to do it twice.
@pyqtSlot(KeyMode)
@pyqtSlot(usertypes.KeyMode)
def on_mode_left(self, mode):
"""Clear up when ommand mode was left.
@ -286,7 +286,7 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
clear_completion_selection: Always emitted.
hide_completion: Always emitted so the completion is hidden.
"""
if mode == KeyMode.command:
if mode == usertypes.KeyMode.command:
self.setText('')
self.history.stop()
self.hide_cmd.emit()
@ -295,14 +295,14 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
def focusInEvent(self, e):
"""Extend focusInEvent to enter command mode."""
modeman.maybe_enter(KeyMode.command, 'cmd focus')
modeman.maybe_enter(usertypes.KeyMode.command, 'cmd focus')
super().focusInEvent(e)
def setText(self, text):
"""Extend setText to set prefix and make sure the prompt is ok."""
if not text:
pass
elif text[0] in STARTCHARS:
elif text[0] in modeparsers.STARTCHARS:
super().set_prompt(text[0])
else:
raise AssertionError("setText got called with invalid text "

View File

@ -19,10 +19,10 @@
"""Keychain string displayed in the statusbar."""
from qutebrowser.widgets.statusbar.textbase import TextBase
from qutebrowser.widgets.statusbar import textbase
class KeyString(TextBase):
class KeyString(textbase.TextBase):
"""Keychain string displayed in the statusbar."""

View File

@ -21,10 +21,10 @@
from PyQt5.QtCore import pyqtSlot
from qutebrowser.widgets.statusbar.textbase import TextBase
from qutebrowser.widgets.statusbar import textbase
class Percentage(TextBase):
class Percentage(textbase.TextBase):
"""Reading percentage displayed in the statusbar."""

View File

@ -22,8 +22,8 @@
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QProgressBar, QSizePolicy
from qutebrowser.widgets.webview import LoadStatus
from qutebrowser.config.style import set_register_stylesheet
from qutebrowser.widgets import webview
from qutebrowser.config import style
class Progress(QProgressBar):
@ -50,7 +50,7 @@ class Progress(QProgressBar):
def __init__(self, parent=None):
super().__init__(parent)
set_register_stylesheet(self)
style.set_register_stylesheet(self)
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Ignored)
self.setTextVisible(False)
self.hide()
@ -72,7 +72,7 @@ class Progress(QProgressBar):
# sometimes.
return
self.setValue(tab.progress)
if tab.load_status == LoadStatus.loading:
if tab.load_status == webview.LoadStatus.loading:
self.show()
else:
self.hide()

View File

@ -22,18 +22,17 @@
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QHBoxLayout, QWidget, QLineEdit
from qutebrowser.widgets.misc import MinimalLineEditMixin
from qutebrowser.widgets.statusbar.textbase import TextBase
from qutebrowser.widgets.statusbar.prompter import Prompter
from qutebrowser.widgets import misc
from qutebrowser.widgets.statusbar import textbase, prompter
class PromptLineEdit(MinimalLineEditMixin, QLineEdit):
class PromptLineEdit(misc.MinimalLineEditMixin, QLineEdit):
"""QLineEdit with a minimal stylesheet."""
def __init__(self, parent=None):
QLineEdit.__init__(self, parent)
MinimalLineEditMixin.__init__(self)
misc.MinimalLineEditMixin.__init__(self)
class Prompt(QWidget):
@ -60,13 +59,13 @@ class Prompt(QWidget):
self._hbox.setContentsMargins(0, 0, 0, 0)
self._hbox.setSpacing(5)
self.txt = TextBase()
self.txt = textbase.TextBase()
self._hbox.addWidget(self.txt)
self.lineedit = PromptLineEdit()
self._hbox.addWidget(self.lineedit)
self.prompter = Prompter(self)
self.prompter = prompter.Prompter(self)
def __repr__(self):
return '<{}>'.format(self.__class__.__name__)

View File

@ -19,20 +19,21 @@
"""Manager for questions to be shown in the statusbar."""
from collections import namedtuple, deque
import collections
from PyQt5.QtCore import pyqtSlot, QTimer
from PyQt5.QtWidgets import QLineEdit
import qutebrowser.keyinput.modeman as modeman
import qutebrowser.commands.utils as cmdutils
from qutebrowser.utils.usertypes import PromptMode, Question, KeyMode
from qutebrowser.utils.qt import EventLoop
from qutebrowser.keyinput import modeman
from qutebrowser.commands import utils as cmdutils
from qutebrowser.utils import usertypes
from qutebrowser.utils import qt as qtutils
from qutebrowser.utils.log import statusbar as logger
PromptContext = namedtuple('PromptContext', ['question', 'text', 'input_text',
'echo_mode', 'input_visible'])
PromptContext = collections.namedtuple('PromptContext',
['question', 'text', 'input_text',
'echo_mode', 'input_visible'])
class Prompter:
@ -67,7 +68,7 @@ class Prompter:
def __init__(self, prompt):
self.question = None
self._loops = []
self._queue = deque()
self._queue = collections.deque()
self._busy = False
self._prompt = prompt
@ -124,7 +125,7 @@ class Prompter:
Raise:
ValueError if the set PromptMode is invalid.
"""
if self.question.mode == PromptMode.yesno:
if self.question.mode == usertypes.PromptMode.yesno:
if self.question.default is None:
suffix = ""
elif self.question.default:
@ -133,23 +134,23 @@ class Prompter:
suffix = " (no)"
self._prompt.txt.setText(self.question.text + suffix)
self._prompt.lineedit.hide()
mode = KeyMode.yesno
elif self.question.mode == PromptMode.text:
mode = usertypes.KeyMode.yesno
elif self.question.mode == usertypes.PromptMode.text:
self._prompt.txt.setText(self.question.text)
if self.question.default:
self._prompt.lineedit.setText(self.question.default)
self._prompt.lineedit.show()
mode = KeyMode.prompt
elif self.question.mode == PromptMode.user_pwd:
mode = usertypes.KeyMode.prompt
elif self.question.mode == usertypes.PromptMode.user_pwd:
self._prompt.txt.setText(self.question.text)
if self.question.default:
self._prompt.lineedit.setText(self.question.default)
self._prompt.lineedit.show()
mode = KeyMode.prompt
elif self.question.mode == PromptMode.alert:
mode = usertypes.KeyMode.prompt
elif self.question.mode == usertypes.PromptMode.alert:
self._prompt.txt.setText(self.question.text + ' (ok)')
self._prompt.lineedit.hide()
mode = KeyMode.prompt
mode = usertypes.KeyMode.prompt
else:
raise ValueError("Invalid prompt mode!")
self._prompt.lineedit.setFocus()
@ -174,10 +175,10 @@ class Prompter:
else:
return False
@pyqtSlot(KeyMode)
@pyqtSlot(usertypes.KeyMode)
def on_mode_left(self, mode):
"""Clear and reset input when the mode was left."""
if mode in (KeyMode.prompt, KeyMode.yesno):
if mode in (usertypes.KeyMode.prompt, usertypes.KeyMode.yesno):
self._prompt.txt.setText('')
self._prompt.lineedit.clear()
self._prompt.lineedit.setEchoMode(QLineEdit.Normal)
@ -187,7 +188,8 @@ class Prompter:
self.question.cancel()
@cmdutils.register(instance='mainwindow.status.prompt.prompter', hide=True,
modes=[KeyMode.prompt, KeyMode.yesno])
modes=[usertypes.KeyMode.prompt,
usertypes.KeyMode.yesno])
def prompt_accept(self):
"""Accept the current prompt.
@ -196,60 +198,60 @@ class Prompter:
This executes the next action depending on the question mode, e.g. asks
for the password or leaves the mode.
"""
if (self.question.mode == PromptMode.user_pwd and
if (self.question.mode == usertypes.PromptMode.user_pwd and
self.question.user is None):
# User just entered an username
self.question.user = self._prompt.lineedit.text()
self._prompt.txt.setText("Password:")
self._prompt.lineedit.clear()
self._prompt.lineedit.setEchoMode(QLineEdit.Password)
elif self.question.mode == PromptMode.user_pwd:
elif self.question.mode == usertypes.PromptMode.user_pwd:
# User just entered a password
password = self._prompt.lineedit.text()
self.question.answer = (self.question.user, password)
modeman.leave(KeyMode.prompt, 'prompt accept')
modeman.leave(usertypes.KeyMode.prompt, 'prompt accept')
self.question.done()
elif self.question.mode == PromptMode.text:
elif self.question.mode == usertypes.PromptMode.text:
# User just entered text.
self.question.answer = self._prompt.lineedit.text()
modeman.leave(KeyMode.prompt, 'prompt accept')
modeman.leave(usertypes.KeyMode.prompt, 'prompt accept')
self.question.done()
elif self.question.mode == PromptMode.yesno:
elif self.question.mode == usertypes.PromptMode.yesno:
# User wants to accept the default of a yes/no question.
self.question.answer = self.question.default
modeman.leave(KeyMode.yesno, 'yesno accept')
modeman.leave(usertypes.KeyMode.yesno, 'yesno accept')
self.question.done()
elif self.question.mode == PromptMode.alert:
elif self.question.mode == usertypes.PromptMode.alert:
# User acknowledged an alert
self.question.answer = None
modeman.leave(KeyMode.prompt, 'alert accept')
modeman.leave(usertypes.KeyMode.prompt, 'alert accept')
self.question.done()
else:
raise ValueError("Invalid question mode!")
@cmdutils.register(instance='mainwindow.status.prompt.prompter', hide=True,
modes=[KeyMode.yesno])
modes=[usertypes.KeyMode.yesno])
def prompt_yes(self):
"""Answer yes to a yes/no prompt."""
if self.question.mode != PromptMode.yesno:
if self.question.mode != usertypes.PromptMode.yesno:
# We just ignore this if we don't have a yes/no question.
return
self.question.answer = True
modeman.leave(KeyMode.yesno, 'yesno accept')
modeman.leave(usertypes.KeyMode.yesno, 'yesno accept')
self.question.done()
@cmdutils.register(instance='mainwindow.status.prompt.prompter', hide=True,
modes=[KeyMode.yesno])
modes=[usertypes.KeyMode.yesno])
def prompt_no(self):
"""Answer no to a yes/no prompt."""
if self.question.mode != PromptMode.yesno:
if self.question.mode != usertypes.PromptMode.yesno:
# We just ignore this if we don't have a yes/no question.
return
self.question.answer = False
modeman.leave(KeyMode.yesno, 'prompt accept')
modeman.leave(usertypes.KeyMode.yesno, 'prompt accept')
self.question.done()
@pyqtSlot(Question, bool)
@pyqtSlot(usertypes.Question, bool)
def ask_question(self, question, blocking):
"""Dispkay a question in the statusbar.
@ -282,12 +284,12 @@ class Prompter:
try:
modeman.enter(mode, 'question asked')
except modeman.ModeLockedError:
if modeman.instance().mode != KeyMode.prompt:
if modeman.instance().mode != usertypes.KeyMode.prompt:
question.abort()
return None
modeman.instance().locked = True
if blocking:
loop = EventLoop()
loop = qtutils.EventLoop()
self._loops.append(loop)
loop.destroyed.connect(lambda: self._loops.remove(loop))
question.completed.connect(loop.quit)

View File

@ -21,11 +21,11 @@
from PyQt5.QtCore import pyqtSlot
import qutebrowser.config.config as config
from qutebrowser.widgets.statusbar.textbase import TextBase
from qutebrowser.config import config
from qutebrowser.widgets.statusbar import textbase
class Text(TextBase):
class Text(textbase.TextBase):
"""Text displayed in the statusbar.

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.qt import qt_ensure_valid
from qutebrowser.utils import qt as qtutils
class TextBase(QLabel):
@ -79,7 +79,7 @@ class TextBase(QLabel):
"""Extend QLabel::resizeEvent to update the elided text afterwards."""
super().resizeEvent(e)
size = e.size()
qt_ensure_valid(size)
qtutils.qt_ensure_valid(size)
self._update_elided_text(size.width())
def paintEvent(self, e):
@ -90,6 +90,6 @@ class TextBase(QLabel):
e.accept()
painter = QPainter(self)
geom = self.geometry()
qt_ensure_valid(geom)
qtutils.qt_ensure_valid(geom)
painter.drawText(0, 0, geom.width(), geom.height(),
self.alignment(), self._elided_text)

View File

@ -21,17 +21,18 @@
from PyQt5.QtCore import pyqtSlot, pyqtProperty, Qt
from qutebrowser.widgets.webview import LoadStatus
from qutebrowser.widgets.statusbar.textbase import TextBase
from qutebrowser.config.style import set_register_stylesheet, get_stylesheet
from qutebrowser.utils.usertypes import enum
from qutebrowser.widgets import webview
from qutebrowser.widgets.statusbar import textbase
from qutebrowser.config import style
from qutebrowser.utils import usertypes
# Note this has entries for success/error/warn from widgets.webview:LoadStatus
UrlType = enum('UrlType', 'success', 'error', 'warn', 'hover', 'normal')
UrlType = usertypes.enum('UrlType', 'success', 'error', 'warn', 'hover',
'normal')
class UrlText(TextBase):
class UrlText(textbase.TextBase):
"""URL displayed in the statusbar.
@ -80,7 +81,7 @@ class UrlText(TextBase):
"""Override TextBase.__init__ to elide in the middle by default."""
super().__init__(parent, Qt.ElideMiddle)
self.setObjectName(self.__class__.__name__)
set_register_stylesheet(self)
style.set_register_stylesheet(self)
self._hover_url = None
self._normal_url = None
self._normal_url_type = UrlType.normal
@ -104,7 +105,7 @@ class UrlText(TextBase):
if not isinstance(val, UrlType):
raise TypeError("Type {} is no UrlType member!".format(val))
self._urltype = val
self.setStyleSheet(get_stylesheet(self.STYLESHEET))
self.setStyleSheet(style.get_stylesheet(self.STYLESHEET))
@property
def hover_url(self):
@ -164,8 +165,9 @@ class UrlText(TextBase):
Args:
status_str: The LoadStatus as string.
"""
status = LoadStatus[status_str]
if status in (LoadStatus.success, LoadStatus.error, LoadStatus.warn):
status = webview.LoadStatus[status_str]
if status in (webview.LoadStatus.success, webview.LoadStatus.error,
webview.LoadStatus.warn):
self.normal_url_type = UrlType[status_str]
else:
self.normal_url_type = UrlType.normal

View File

@ -19,29 +19,25 @@
"""The main tabbed browser widget."""
from functools import partial
import functools
from PyQt5.QtWidgets import QSizePolicy
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QSize, QTimer
from PyQt5.QtGui import QIcon
from PyQt5.QtWebKitWidgets import QWebPage
import qutebrowser.config.config as config
import qutebrowser.commands.utils as cmdutils
import qutebrowser.keyinput.modeman as modeman
import qutebrowser.utils.log as log
import qutebrowser.utils.misc as utils
import qutebrowser.utils.message as message
from qutebrowser.widgets.tabwidget import TabWidget
from qutebrowser.widgets.webview import WebView
from qutebrowser.browser.signalfilter import SignalFilter
from qutebrowser.browser.commands import CommandDispatcher
from qutebrowser.utils.qt import qt_ensure_valid, QtValueError
from qutebrowser.commands.exceptions import CommandError
from qutebrowser.utils.usertypes import KeyMode
from qutebrowser.config import config
from qutebrowser.commands import utils as cmdutils
from qutebrowser.commands import exceptions as cmdexc
from qutebrowser.keyinput import modeman
from qutebrowser.widgets import tabwidget, webview
from qutebrowser.browser import signalfilter, commands
from qutebrowser.utils import log, message, usertypes
from qutebrowser.utils import misc as utils
from qutebrowser.utils import qt as qtutils
class TabbedBrowser(TabWidget):
class TabbedBrowser(tabwidget.TabWidget):
"""A TabWidget with QWebViews inside.
@ -104,7 +100,7 @@ class TabbedBrowser(TabWidget):
quit = pyqtSignal()
resized = pyqtSignal('QRect')
got_cmd = pyqtSignal(str)
current_tab_changed = pyqtSignal(WebView)
current_tab_changed = pyqtSignal(webview.WebView)
title_changed = pyqtSignal(str)
def __init__(self, parent=None):
@ -116,8 +112,8 @@ class TabbedBrowser(TabWidget):
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self._tabs = []
self.url_stack = []
self._filter = SignalFilter(self)
self.cmd = CommandDispatcher(self)
self._filter = signalfilter.SignalFilter(self)
self.cmd = commands.CommandDispatcher(self)
self.last_focused = None
self._now_focused = None
# FIXME adjust this to font size
@ -159,7 +155,8 @@ class TabbedBrowser(TabWidget):
self._filter.create(self.cur_url_text_changed, tab))
tab.load_status_changed.connect(
self._filter.create(self.cur_load_status_changed, tab))
tab.url_text_changed.connect(partial(self.on_url_text_changed, tab))
tab.url_text_changed.connect(
functools.partial(self.on_url_text_changed, tab))
# hintmanager
tab.hintmanager.hint_strings_updated.connect(self.hint_strings_updated)
tab.hintmanager.download_get.connect(self.download_get)
@ -168,13 +165,18 @@ class TabbedBrowser(TabWidget):
# downloads
page.start_download.connect(self.start_download)
# misc
tab.titleChanged.connect(partial(self.on_title_changed, tab))
tab.iconChanged.connect(partial(self.on_icon_changed, tab))
tab.loadProgress.connect(partial(self.on_load_progress, tab))
frame.loadFinished.connect(partial(self.on_load_finished, tab))
frame.loadStarted.connect(partial(self.on_load_started, tab))
tab.titleChanged.connect(
functools.partial(self.on_title_changed, tab))
tab.iconChanged.connect(
functools.partial(self.on_icon_changed, tab))
tab.loadProgress.connect(
functools.partial(self.on_load_progress, tab))
frame.loadFinished.connect(
functools.partial(self.on_load_finished, tab))
frame.loadStarted.connect(
functools.partial(self.on_load_started, tab))
page.windowCloseRequested.connect(
partial(self.on_window_close_requested, tab))
functools.partial(self.on_window_close_requested, tab))
def cntwidget(self, count=None):
"""Return a widget based on a count/idx.
@ -208,13 +210,13 @@ class TabbedBrowser(TabWidget):
"""
url = self.currentWidget().cur_url
try:
qt_ensure_valid(url)
except QtValueError as e:
qtutils.qt_ensure_valid(url)
except qtutils.QtValueError as e:
msg = "Current URL is invalid"
if e.reason:
msg += " ({})".format(e.reason)
msg += "!"
raise CommandError(msg)
raise cmdexc.CommandError(msg)
return url
def shutdown(self):
@ -264,7 +266,7 @@ class TabbedBrowser(TabWidget):
if tab is self.last_focused:
self.last_focused = None
if not tab.cur_url.isEmpty():
qt_ensure_valid(tab.cur_url)
qtutils.qt_ensure_valid(tab.cur_url)
self.url_stack.append(tab.cur_url)
tab.shutdown()
self._tabs.remove(tab)
@ -279,7 +281,7 @@ class TabbedBrowser(TabWidget):
url: The URL to open as QUrl.
newtab: True to open URL in a new tab, False otherwise.
"""
qt_ensure_valid(url)
qtutils.qt_ensure_valid(url)
if newtab:
self.tabopen(url, background=False)
else:
@ -295,7 +297,7 @@ class TabbedBrowser(TabWidget):
return
self.close_tab(tab)
@pyqtSlot(WebView)
@pyqtSlot(webview.WebView)
def on_window_close_requested(self, widget):
"""Close a tab with a widget given."""
self.close_tab(widget)
@ -322,9 +324,9 @@ class TabbedBrowser(TabWidget):
The opened WebView instance.
"""
if url is not None:
qt_ensure_valid(url)
qtutils.qt_ensure_valid(url)
log.webview.debug("Creating new tab with URL {}".format(url))
tab = WebView(self)
tab = webview.WebView(self)
self._connect_tab_signals(tab)
self._tabs.append(tab)
if explicit:
@ -440,10 +442,10 @@ class TabbedBrowser(TabWidget):
@pyqtSlot()
def on_cur_load_started(self):
"""Leave insert/hint mode when loading started."""
modeman.maybe_leave(KeyMode.insert, 'load started')
modeman.maybe_leave(KeyMode.hint, 'load started')
modeman.maybe_leave(usertypes.KeyMode.insert, 'load started')
modeman.maybe_leave(usertypes.KeyMode.hint, 'load started')
@pyqtSlot(WebView, str)
@pyqtSlot(webview.WebView, str)
def on_title_changed(self, tab, text):
"""Set the title of a tab.
@ -470,7 +472,7 @@ class TabbedBrowser(TabWidget):
if idx == self.currentIndex():
self.title_changed.emit('{} - qutebrowser'.format(text))
@pyqtSlot(WebView, str)
@pyqtSlot(webview.WebView, str)
def on_url_text_changed(self, tab, url):
"""Set the new URL as title if there's no title yet.
@ -490,7 +492,7 @@ class TabbedBrowser(TabWidget):
if not self.tabText(idx):
self.setTabText(idx, url)
@pyqtSlot(WebView)
@pyqtSlot(webview.WebView)
def on_icon_changed(self, tab):
"""Set the icon of a tab.
@ -512,10 +514,10 @@ class TabbedBrowser(TabWidget):
return
self.setTabIcon(idx, tab.icon())
@pyqtSlot(KeyMode)
@pyqtSlot(usertypes.KeyMode)
def on_mode_left(self, mode):
"""Give focus to current tab if command mode was left."""
if mode == KeyMode.command:
if mode == usertypes.KeyMode.command:
self.currentWidget().setFocus()
@pyqtSlot(int)
@ -523,7 +525,7 @@ class TabbedBrowser(TabWidget):
"""Set last_focused and leave hinting mode when focus changed."""
tab = self.widget(idx)
tab.setFocus()
modeman.maybe_leave(KeyMode.hint, 'tab changed')
modeman.maybe_leave(usertypes.KeyMode.hint, 'tab changed')
self.last_focused = self._now_focused
self._now_focused = tab
self.current_tab_changed.emit(tab)

View File

@ -32,8 +32,8 @@ from PyQt5.QtWidgets import (QTabWidget, QTabBar, QSizePolicy, QCommonStyle,
QApplication)
from PyQt5.QtGui import QIcon, QPalette, QColor
from qutebrowser.utils.qt import qt_ensure_valid
import qutebrowser.config.config as config
from qutebrowser.utils import qt as qtutils
from qutebrowser.config import config
PM_TabBarPadding = QStyle.PM_CustomBase
@ -211,7 +211,7 @@ class TabBar(QTabBar):
# If we *do* have enough space, tabs should occupy the whole window
# width.
size = QSize(self.width() / self.count(), height)
qt_ensure_valid(size)
qtutils.qt_ensure_valid(size)
return size
def paintEvent(self, _e):
@ -311,7 +311,7 @@ class TabBarStyle(QCommonStyle):
elif element == QStyle.CE_TabBarTabLabel:
text_rect, icon_rect = self._tab_layout(opt)
if not opt.icon.isNull():
qt_ensure_valid(icon_rect)
qtutils.qt_ensure_valid(icon_rect)
icon_mode = (QIcon.Normal if opt.state & QStyle.State_Enabled
else QIcon.Disabled)
icon_state = (QIcon.On if opt.state & QStyle.State_Selected
@ -382,7 +382,7 @@ class TabBarStyle(QCommonStyle):
padding = self.pixelMetric(PM_TabBarPadding, opt)
icon_rect = QRect()
text_rect = QRect(opt.rect)
qt_ensure_valid(text_rect)
qtutils.qt_ensure_valid(text_rect)
indicator_width = config.get('tabs', 'indicator-width')
text_rect.adjust(padding, 0, 0, 0)
if indicator_width != 0:
@ -419,5 +419,5 @@ class TabBarStyle(QCommonStyle):
text_rect.center().y() - tab_icon_size.height() / 2,
tab_icon_size.width(), tab_icon_size.height())
icon_rect = self._style.visualRect(opt.direction, opt.rect, icon_rect)
qt_ensure_valid(icon_rect)
qtutils.qt_ensure_valid(icon_rect)
return icon_rect

View File

@ -24,21 +24,17 @@ from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebKit import QWebSettings
from PyQt5.QtWebKitWidgets import QWebView, QWebPage
import qutebrowser.config.config as config
import qutebrowser.keyinput.modeman as modeman
import qutebrowser.utils.message as message
import qutebrowser.utils.webelem as webelem
import qutebrowser.utils.log as log
from qutebrowser.utils.misc import elide
from qutebrowser.utils.qt import qt_ensure_valid
from qutebrowser.browser.webpage import BrowserPage
from qutebrowser.browser.hints import HintManager
from qutebrowser.utils.usertypes import (NeighborList, ClickTarget, KeyMode,
enum)
from qutebrowser.commands.exceptions import CommandError
from qutebrowser.config import config
from qutebrowser.keyinput import modeman
from qutebrowser.utils import message, webelem, log, usertypes
from qutebrowser.utils import misc as utils
from qutebrowser.utils import qt as qtutils
from qutebrowser.browser import webpage, hints
from qutebrowser.commands import exceptions as cmdexc
LoadStatus = enum('LoadStatus', 'none', 'success', 'error', 'warn', 'loading')
LoadStatus = usertypes.enum('LoadStatus', 'none', 'success', 'error', 'warn',
'loading')
class WebView(QWebView):
@ -93,7 +89,7 @@ class WebView(QWebView):
self.statusbar_message = ''
self._old_scroll_pos = (-1, -1)
self._open_target = None
self.open_target = ClickTarget.normal
self.open_target = usertypes.ClickTarget.normal
self._force_open_target = None
self._zoom = None
self._has_ssl_errors = False
@ -101,9 +97,9 @@ class WebView(QWebView):
self._cur_url = None
self.cur_url = QUrl()
self.progress = 0
self._page = BrowserPage(self)
self._page = webpage.BrowserPage(self)
self.setPage(self._page)
self.hintmanager = HintManager(self)
self.hintmanager = hints.HintManager(self)
self.hintmanager.mouse_event.connect(self.on_mouse_event)
self.hintmanager.set_open_target.connect(self.set_force_open_target)
self._page.linkHovered.connect(self.linkHovered)
@ -120,7 +116,7 @@ class WebView(QWebView):
def __repr__(self):
url = self.url().toDisplayString()
return "WebView(url='{}')".format(elide(url, 50))
return "WebView(url='{}')".format(utils.elide(url, 50))
@property
def open_target(self):
@ -130,7 +126,7 @@ class WebView(QWebView):
@open_target.setter
def open_target(self, val):
"""Setter for open_target to do type checking."""
if not isinstance(val, ClickTarget):
if not isinstance(val, usertypes.ClickTarget):
raise TypeError("Target {} is no ClickTarget member!".format(val))
self._open_target = val
@ -172,9 +168,10 @@ class WebView(QWebView):
def _init_neighborlist(self):
"""Initialize the _zoom neighborlist."""
self._zoom = NeighborList(config.get('ui', 'zoom-levels'),
default=config.get('ui', 'default-zoom'),
mode=NeighborList.Modes.block)
levels = config.get('ui', 'zoom-levels')
default = config.get('ui', 'default-zoom')
self._zoom = usertypes.NeighborList(
levels, default, mode=usertypes.NeighborList.Modes.block)
def _mousepress_backforward(self, e):
"""Handle back/forward mouse button presses.
@ -186,13 +183,13 @@ class WebView(QWebView):
# Back button on mice which have it.
try:
self.go_back()
except CommandError as ex:
except cmdexc.CommandError as ex:
message.error(ex, immediately=True)
elif e.button() == Qt.XButton2:
# Forward button on mice which have it.
try:
self.go_forward()
except CommandError as ex:
except cmdexc.CommandError as ex:
message.error(ex, immediately=True)
def _mousepress_insertmode(self, e):
@ -233,11 +230,11 @@ class WebView(QWebView):
elif ((hitresult.isContentEditable() and webelem.is_writable(elem)) or
webelem.is_editable(elem)):
log.mouse.debug("Clicked editable element!")
modeman.maybe_enter(KeyMode.insert, 'click')
modeman.maybe_enter(usertypes.KeyMode.insert, 'click')
else:
log.mouse.debug("Clicked non-editable element!")
if config.get('input', 'auto-leave-insert-mode'):
modeman.maybe_leave(KeyMode.insert, 'click')
modeman.maybe_leave(usertypes.KeyMode.insert, 'click')
def mouserelease_insertmode(self):
"""If we have an insertmode check scheduled, handle it."""
@ -247,11 +244,11 @@ class WebView(QWebView):
elem = webelem.focus_elem(self.page().currentFrame())
if webelem.is_editable(elem):
log.mouse.debug("Clicked editable element (delayed)!")
modeman.maybe_enter(KeyMode.insert, 'click-delayed')
modeman.maybe_enter(usertypes.KeyMode.insert, 'click-delayed')
else:
log.mouse.debug("Clicked non-editable element (delayed)!")
if config.get('input', 'auto-leave-insert-mode'):
modeman.maybe_leave(KeyMode.insert, 'click-delayed')
modeman.maybe_leave(usertypes.KeyMode.insert, 'click-delayed')
def _mousepress_opentarget(self, e):
"""Set the open target when something was clicked.
@ -267,13 +264,13 @@ class WebView(QWebView):
elif (e.button() == Qt.MidButton or
e.modifiers() & Qt.ControlModifier):
if config.get('tabs', 'background-tabs'):
self.open_target = ClickTarget.tab_bg
self.open_target = usertypes.ClickTarget.tab_bg
else:
self.open_target = ClickTarget.tab
self.open_target = usertypes.ClickTarget.tab
log.mouse.debug("Middle click, setting target: {}".format(
self.open_target))
else:
self.open_target = ClickTarget.normal
self.open_target = usertypes.ClickTarget.normal
log.mouse.debug("Normal click, setting normal target")
def shutdown(self):
@ -304,7 +301,7 @@ class WebView(QWebView):
Emit:
titleChanged
"""
qt_ensure_valid(url)
qtutils.qt_ensure_valid(url)
urlstr = url.toDisplayString()
log.webview.debug("New title: {}".format(urlstr))
self.titleChanged.emit(urlstr)
@ -321,7 +318,7 @@ class WebView(QWebView):
if fuzzyval:
self._zoom.fuzzyval = int(perc)
if perc < 0:
raise CommandError("Can't zoom {}%!".format(perc))
raise cmdexc.CommandError("Can't zoom {}%!".format(perc))
self.setZoomFactor(float(perc) / 100)
message.info("Zoom level: {}%".format(perc))
@ -349,19 +346,19 @@ class WebView(QWebView):
if self.page().history().canGoBack():
self.back()
else:
raise CommandError("At beginning of history.")
raise cmdexc.CommandError("At beginning of history.")
def go_forward(self):
"""Go forward a page in the history."""
if self.page().history().canGoForward():
self.forward()
else:
raise CommandError("At end of history.")
raise cmdexc.CommandError("At end of history.")
@pyqtSlot('QUrl')
def on_url_changed(self, url):
"""Update cur_url when URL has changed."""
qt_ensure_valid(url)
qtutils.qt_ensure_valid(url)
self.cur_url = url
@pyqtSlot(str, str)
@ -394,7 +391,7 @@ class WebView(QWebView):
self.load_status = LoadStatus.error
if not config.get('input', 'auto-insert-mode'):
return
if modeman.instance().mode == KeyMode.insert or not ok:
if modeman.instance().mode == usertypes.KeyMode.insert or not ok:
return
frame = self.page().currentFrame()
elem = frame.findFirstElement(':focus')
@ -402,7 +399,7 @@ class WebView(QWebView):
if elem.isNull():
log.webview.debug("Focused element is null!")
elif webelem.is_editable(elem):
modeman.maybe_enter(KeyMode.insert, 'load finished')
modeman.maybe_enter(usertypes.KeyMode.insert, 'load finished')
@pyqtSlot(str)
def set_force_open_target(self, target):
@ -411,7 +408,7 @@ class WebView(QWebView):
Args:
target: A string to set self._force_open_target to.
"""
t = getattr(ClickTarget, target)
t = getattr(usertypes.ClickTarget, target)
log.webview.debug("Setting force target to {}/{}".format(target, t))
self._force_open_target = t

View File

@ -25,7 +25,7 @@ import os.path
import sys
import glob
import shutil
from fnmatch import fnmatch
import fnmatch
recursive_lint = ('__pycache__', '*.pyc')
@ -47,11 +47,17 @@ def remove(path):
os.remove(path)
for elem in lint:
for f in glob.glob(elem):
remove(f)
def main():
"""Clean up lint in the current dir."""
for elem in lint:
for f in glob.glob(elem):
remove(f)
for root, _dirs, _files in os.walk(os.getcwd()):
path = os.path.basename(root)
if any([fnmatch.fnmatch(path, e) for e in recursive_lint]):
remove(root)
for root, dirs, files in os.walk(os.getcwd()):
if any([fnmatch(os.path.basename(root), e) for e in recursive_lint]):
remove(root)
if __name__ == '__main__':
main()

View File

@ -27,12 +27,12 @@ Builds a standalone executable.
import os
import os.path
import sys
from distutils.sysconfig import get_python_lib
import distutils
from cx_Freeze import setup, Executable
import cx_Freeze as cx
sys.path.insert(0, os.getcwd())
from scripts.setupcommon import setupdata, write_git_file
from scripts import setupcommon
try:
@ -46,7 +46,8 @@ def get_egl_path():
"""Get the path for PyQt5's libEGL.dll."""
if not sys.platform.startswith('win'):
return None
return os.path.join(get_python_lib(), r'PyQt5\libEGL.dll')
return os.path.join(distutils.sysconfig.get_python_lib(),
r'PyQt5\libEGL.dll')
build_exe_options = {
'include_files': [
@ -69,20 +70,20 @@ bdist_msi_options = {
base = 'Win32GUI' if sys.platform.startswith('win') else None
executable = Executable('qutebrowser/__main__.py', base=base,
targetName='qutebrowser.exe',
shortcutName='qutebrowser',
shortcutDir='ProgramMenuFolder')
executable = cx.Executable('qutebrowser/__main__.py', base=base,
targetName='qutebrowser.exe',
shortcutName='qutebrowser',
shortcutDir='ProgramMenuFolder')
try:
write_git_file()
setup(
setupcommon.write_git_file()
cx.setup(
executables=[executable],
options={
'build_exe': build_exe_options,
'bdist_msi': bdist_msi_options,
},
**setupdata
**setupcommon.setupdata
)
finally:
if BASEDIR is not None:

View File

@ -27,18 +27,18 @@ import html
import shutil
import inspect
import subprocess
from collections import Counter, OrderedDict
from tempfile import mkstemp
import collections
import tempfile
sys.path.insert(0, os.getcwd())
import qutebrowser
# We import qutebrowser.app so all @cmdutils-register decorators are run.
import qutebrowser.app
import qutebrowser.commands.utils as cmdutils
import qutebrowser.config.configdata as configdata
import qutebrowser.qutebrowser as qutequtebrowser
from qutebrowser.utils.usertypes import enum
from qutebrowser import qutebrowser as qutequtebrowser
from qutebrowser.commands import utils as cmdutils
from qutebrowser.config import configdata
from qutebrowser.utils import usertypes
def _open_file(name, mode='w'):
@ -58,8 +58,9 @@ def _parse_docstring(func): # noqa
A (short_desc, long_desc, arg_descs) tuple.
"""
# pylint: disable=too-many-branches
State = enum('State', 'short', 'desc', # pylint: disable=invalid-name
'desc_hidden', 'arg_start', 'arg_inside', 'misc')
State = usertypes.enum('State', 'short', # pylint: disable=invalid-name
'desc', 'desc_hidden', 'arg_start', 'arg_inside',
'misc')
doc = inspect.getdoc(func)
lines = doc.splitlines()
@ -67,7 +68,7 @@ def _parse_docstring(func): # noqa
short_desc = []
long_desc = []
arg_descs = OrderedDict()
arg_descs = collections.OrderedDict()
cur_arg_name = None
for line in lines:
@ -385,7 +386,7 @@ def generate_settings(f):
def _get_authors():
"""Get a list of authors based on git commit logs."""
commits = subprocess.check_output(['git', 'log', '--format=%aN'])
cnt = Counter(commits.decode('utf-8').splitlines())
cnt = collections.Counter(commits.decode('utf-8').splitlines())
return sorted(cnt, key=lambda k: cnt[k])
@ -442,7 +443,7 @@ def generate_manpage_resources(f):
def regenerate_authors(filename):
"""Re-generate the authors inside README based on the commits made."""
oshandle, tmpname = mkstemp()
oshandle, tmpname = tempfile.mkstemp()
with _open_file(filename, mode='r') as infile, \
_open_file(oshandle, mode='w') as temp:
ignore = False

View File

@ -20,18 +20,17 @@
"""Custom astroid checker for config calls."""
import astroid
from pylint.interfaces import IAstroidChecker
from pylint.checkers import BaseChecker
from pylint import interfaces, checkers
from pylint.checkers import utils
import qutebrowser.config.configdata as configdata
from qutebrowser.config import configdata
class ConfigChecker(BaseChecker):
class ConfigChecker(checkers.BaseChecker):
"""Custom astroid checker for config calls."""
__implements__ = IAstroidChecker
__implements__ = interfaces.IAstroidChecker
name = 'config'
msgs = {
'E0000': ('"%s -> %s" is no valid config option.', 'bad-config-call',

View File

@ -18,15 +18,14 @@
"""Checker for CRLF in files."""
from pylint.interfaces import IRawChecker
from pylint.checkers import BaseChecker
from pylint import interfaces, checkers
class CrlfChecker(BaseChecker):
class CrlfChecker(checkers.BaseChecker):
"""Check for CRLF in files."""
__implements__ = IRawChecker
__implements__ = interfaces.IRawChecker
name = 'crlf'
msgs = {'W9001': ('Uses CRLFs', 'crlf', None)}

View File

@ -20,15 +20,14 @@
import os.path
from pylint.interfaces import IRawChecker
from pylint.checkers import BaseChecker
from pylint import interfaces, checkers
class ModelineChecker(BaseChecker):
class ModelineChecker(checkers.BaseChecker):
"""Check for vim modelines in files."""
__implements__ = IRawChecker
__implements__ = interfaces.IRawChecker
name = 'modeline'
msgs = {'W9002': ('Does not have vim modeline', 'modeline-missing', None),

View File

@ -20,16 +20,15 @@
"""Make sure open() has an encoding set."""
import astroid
from pylint.interfaces import IAstroidChecker
from pylint.checkers import BaseChecker
from pylint import interfaces, checkers
from pylint.checkers import utils
class OpenEncodingChecker(BaseChecker):
class OpenEncodingChecker(checkers.BaseChecker):
"""Checker to check open() has an encoding set."""
__implements__ = IAstroidChecker
__implements__ = interfaces.IAstroidChecker
name = 'open-encoding'
msgs = {

View File

@ -38,13 +38,13 @@ import logging
import tokenize
import configparser
import argparse
from collections import OrderedDict
from functools import partial
from contextlib import contextmanager
import collections
import functools
import contextlib
import colorama as col
import pep257
from pkg_resources import load_entry_point, DistributionNotFound
import pkg_resources as pkg
sys.path.insert(0, os.getcwd())
@ -59,7 +59,7 @@ config = configparser.ConfigParser()
config.read('.run_checks')
@contextmanager
@contextlib.contextmanager
def _adjusted_pythonpath(name):
"""Adjust PYTHONPATH for pylint."""
if name == 'pylint':
@ -82,7 +82,7 @@ def _run_distutils(name, args):
"""Run a checker via its distutils entry point."""
sys.argv = [name] + args
try:
ep = load_entry_point(name, 'console_scripts', name)
ep = pkg.load_entry_point(name, 'console_scripts', name)
ep()
except SystemExit as e:
return e.code
@ -114,7 +114,7 @@ def run(name, target=None):
with _adjusted_pythonpath(name):
try:
status = _run_distutils(name, args)
except DistributionNotFound:
except pkg.DistributionNotFound:
status = _run_subprocess(name, args)
print()
return status
@ -244,23 +244,23 @@ def _get_args(checker):
def _get_checkers():
"""Get a dict of checkers we need to execute."""
# "Static" checkers
checkers = OrderedDict([
('global', OrderedDict([
checkers = collections.OrderedDict([
('global', collections.OrderedDict([
('unittest', check_unittest),
('git', check_git),
])),
('setup', OrderedDict([
('pyroma', partial(run, 'pyroma')),
('check-manifest', partial(run, 'check-manifest')),
('setup', collections.OrderedDict([
('pyroma', functools.partial(run, 'pyroma')),
('check-manifest', functools.partial(run, 'check-manifest')),
])),
])
# "Dynamic" checkers which exist once for each target.
for target in config.get('DEFAULT', 'targets').split(','):
checkers[target] = OrderedDict([
('pep257', partial(check_pep257, target)),
('flake8', partial(run, 'flake8', target)),
('vcs', partial(check_vcs_conflict, target)),
('pylint', partial(run, 'pylint', target)),
checkers[target] = collections.OrderedDict([
('pep257', functools.partial(check_pep257, target)),
('flake8', functools.partial(run, 'flake8', target)),
('vcs', functools.partial(check_vcs_conflict, target)),
('pylint', functools.partial(run, 'pylint', target)),
])
return checkers
@ -279,7 +279,7 @@ def _checker_enabled(args, group, name):
def main():
"""Main entry point."""
col.init()
exit_status = OrderedDict()
exit_status = collections.OrderedDict()
exit_status_bool = {}
parser = argparse.ArgumentParser(description='Run various checkers.')
parser.add_argument('-s', '--setup', help="Run additional setup checks",

View File

@ -23,20 +23,20 @@
import sys
import cProfile
import os.path
from os import getcwd
from tempfile import mkdtemp
from subprocess import call
from shutil import rmtree
import os
import tempfile
import subprocess
import shutil
sys.path.insert(0, getcwd())
sys.path.insert(0, os.getcwd())
import qutebrowser.qutebrowser # pylint: disable=unused-import
tempdir = mkdtemp()
tempdir = tempfile.mkdtemp()
if '--profile-keep' in sys.argv:
sys.argv.remove('--profile-keep')
profilefile = os.path.join(getcwd(), 'profile')
profilefile = os.path.join(os.getcwd(), 'profile')
else:
profilefile = os.path.join(tempdir, 'profile')
if '--profile-noconv' in sys.argv:
@ -51,5 +51,6 @@ profiler.run('qutebrowser.qutebrowser.main()')
profiler.dump_stats(profilefile)
if not noconv:
call(['pyprof2calltree', '-k', '-i', profilefile, '-o', callgraphfile])
rmtree(tempdir)
subprocess.call(['pyprof2calltree', '-k', '-i', profilefile,
'-o', callgraphfile])
shutil.rmtree(tempdir)

View File

@ -20,7 +20,8 @@
"""Update 3rd-party files (currently only ez_setup.py)."""
from urllib.request import urlretrieve
import urllib.request
urlretrieve('https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py',
'scripts/ez_setup.py')
urllib.request.urlretrieve(
'https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py',
'scripts/ez_setup.py')

View File

@ -24,11 +24,11 @@
import os
import os.path
from scripts.setupcommon import setupdata, write_git_file
from scripts import setupcommon as common
from scripts.ez_setup import use_setuptools
use_setuptools()
from setuptools import setup, find_packages
from scripts import ez_setup
ez_setup.use_setuptools()
import setuptools
try:
@ -38,9 +38,9 @@ except NameError:
try:
write_git_file()
setup(
packages=find_packages(exclude=['qutebrowser.test']),
common.write_git_file()
setuptools.setup(
packages=setuptools.find_packages(exclude=['qutebrowser.test']),
include_package_data=True,
package_data={'qutebrowser': ['html/*', 'git-commit-id']},
entry_points={'gui_scripts':
@ -51,7 +51,7 @@ try:
extras_require={'nice-debugging': ['colorlog', 'colorama'],
'checks': ['flake8', 'pylint', 'check-manifest',
'pyroma']},
**setupdata
**common.setupdata
)
finally:
if BASEDIR is not None: