Fix startup crashes after config merge.
Get qutebrowser to the point where it can at least start - Declare _messages earlier in MessageView.__init__ so it is set before the config trigger tries to access it. - Remove unused configmodel completion functions - Move bind completion to configmodel to avoid a circular import with the config module - Fix some config accesses (forgot to use .val) - Fix old Completion.CompletionKind references
This commit is contained in:
parent
71b71dbc58
commit
5ea420b49b
@ -44,7 +44,6 @@ import qutebrowser.resources
|
||||
from qutebrowser.completion.models import miscmodels
|
||||
from qutebrowser.commands import cmdutils, runners, cmdexc
|
||||
from qutebrowser.config import config, websettings, configexc
|
||||
from qutebrowser.config.parsers import keyconf
|
||||
from qutebrowser.browser import (urlmarks, adblock, history, browsertab,
|
||||
downloads)
|
||||
from qutebrowser.browser.network import proxy
|
||||
@ -412,9 +411,6 @@ def _init_modules(args, crash_handler):
|
||||
config.init(qApp)
|
||||
save_manager.init_autosave()
|
||||
|
||||
log.init.debug("Initializing keys...")
|
||||
keyconf.init(qApp)
|
||||
|
||||
log.init.debug("Initializing sql...")
|
||||
try:
|
||||
sql.init(os.path.join(standarddir.data(), 'history.sqlite'))
|
||||
@ -631,7 +627,7 @@ class Quitter:
|
||||
return True
|
||||
|
||||
@cmdutils.register(instance='quitter', name='quit')
|
||||
@cmdutils.argument('session', completion=usertypes.Completion.sessions)
|
||||
@cmdutils.argument('session', completion=miscmodels.session)
|
||||
def quit(self, save=False, session=None):
|
||||
"""Quit qutebrowser.
|
||||
|
||||
|
@ -33,6 +33,7 @@ from PyQt5.QtPrintSupport import QPrinter
|
||||
|
||||
from qutebrowser.browser import browsertab
|
||||
from qutebrowser.browser.webkit import webview, tabhistory, webkitelem
|
||||
from qutebrowser.browser.network import proxy
|
||||
from qutebrowser.utils import qtutils, objreg, usertypes, utils, log, debug
|
||||
|
||||
|
||||
|
@ -19,78 +19,61 @@
|
||||
|
||||
"""Functions that return config-related completion models."""
|
||||
|
||||
from qutebrowser.config import configdata, configexc
|
||||
from qutebrowser.config import configdata, configexc, config
|
||||
from qutebrowser.completion.models import completionmodel, listcategory
|
||||
from qutebrowser.utils import objreg
|
||||
from qutebrowser.commands import cmdutils
|
||||
|
||||
|
||||
def section():
|
||||
"""A CompletionModel filled with settings sections."""
|
||||
model = completionmodel.CompletionModel(column_widths=(20, 70, 10))
|
||||
sections = ((name, configdata.SECTION_DESC[name].splitlines()[0].strip())
|
||||
for name in configdata.DATA)
|
||||
model.add_category(listcategory.ListCategory("Sections", sections))
|
||||
def option():
|
||||
"""A CompletionModel filled with settings and their descriptions."""
|
||||
model = completionmodel.CompletionModel(column_widths=(30, 70, 0))
|
||||
options = [(x.name, x.description) for x in configdata.DATA.values()]
|
||||
model.add_category(listcategory.ListCategory("Options", options))
|
||||
return model
|
||||
|
||||
|
||||
def option(sectname):
|
||||
"""A CompletionModel filled with settings and their descriptions.
|
||||
|
||||
Args:
|
||||
sectname: The name of the config section this model shows.
|
||||
"""
|
||||
model = completionmodel.CompletionModel(column_widths=(20, 70, 10))
|
||||
try:
|
||||
sectdata = configdata.DATA[sectname]
|
||||
except KeyError:
|
||||
return None
|
||||
options = []
|
||||
for name in sectdata:
|
||||
try:
|
||||
desc = sectdata.descriptions[name]
|
||||
except (KeyError, AttributeError):
|
||||
# Some stuff (especially ValueList items) don't have a
|
||||
# description.
|
||||
desc = ""
|
||||
else:
|
||||
desc = desc.splitlines()[0]
|
||||
config = objreg.get('config')
|
||||
val = config.get(sectname, name, raw=True)
|
||||
options.append((name, desc, val))
|
||||
model.add_category(listcategory.ListCategory(sectname, options))
|
||||
return model
|
||||
|
||||
|
||||
def value(sectname, optname):
|
||||
def value(optname, *values):
|
||||
"""A CompletionModel filled with setting values.
|
||||
|
||||
Args:
|
||||
sectname: The name of the config section this model shows.
|
||||
optname: The name of the config option this model shows.
|
||||
values: The values already provided on the command line.
|
||||
"""
|
||||
model = completionmodel.CompletionModel(column_widths=(20, 70, 10))
|
||||
config = objreg.get('config')
|
||||
model = completionmodel.CompletionModel(column_widths=(30, 70, 0))
|
||||
|
||||
try:
|
||||
current = config.get(sectname, optname, raw=True) or '""'
|
||||
except (configexc.NoSectionError, configexc.NoOptionError):
|
||||
current = str(config.instance.get(optname) or '""')
|
||||
except configexc.NoOptionError:
|
||||
return None
|
||||
|
||||
default = configdata.DATA[sectname][optname].default() or '""'
|
||||
|
||||
if hasattr(configdata.DATA[sectname], 'valtype'):
|
||||
# Same type for all values (ValueList)
|
||||
vals = configdata.DATA[sectname].valtype.complete()
|
||||
else:
|
||||
if optname is None:
|
||||
raise ValueError("optname may only be None for ValueList "
|
||||
"sections, but {} is not!".format(sectname))
|
||||
# Different type for each value (KeyValue)
|
||||
vals = configdata.DATA[sectname][optname].typ.complete()
|
||||
|
||||
opt = configdata.DATA[optname]
|
||||
default = str(opt.default or '""')
|
||||
cur_cat = listcategory.ListCategory("Current/Default",
|
||||
[(current, "Current value"), (default, "Default value")])
|
||||
model.add_category(cur_cat)
|
||||
|
||||
vals = opt.typ.complete()
|
||||
if vals is not None:
|
||||
model.add_category(listcategory.ListCategory("Completions", vals))
|
||||
return model
|
||||
|
||||
|
||||
def bind(key):
|
||||
"""A CompletionModel filled with all bindable commands and descriptions.
|
||||
|
||||
Args:
|
||||
key: the key being bound.
|
||||
"""
|
||||
model = completionmodel.CompletionModel(column_widths=(20, 60, 20))
|
||||
cmd_text = objreg.get('key-config').get_bindings_for('normal').get(key)
|
||||
|
||||
if cmd_text:
|
||||
cmd_name = cmd_text.split(' ')[0]
|
||||
cmd = cmdutils.cmd_dict.get(cmd_name)
|
||||
data = [(cmd_text, cmd.desc, key)]
|
||||
model.add_category(listcategory.ListCategory("Current", data))
|
||||
|
||||
#cmdlist = _get_cmd_completions(include_hidden=True, include_aliases=True)
|
||||
#model.add_category(listcategory.ListCategory("Commands", cmdlist))
|
||||
return model
|
||||
|
@ -39,7 +39,7 @@ class HistoryCategory(QSqlQueryModel):
|
||||
|
||||
# replace ' in timestamp-format to avoid breaking the query
|
||||
timefmt = ("strftime('{}', last_atime, 'unixepoch', 'localtime')"
|
||||
.format(config.get('completion', 'timestamp-format')
|
||||
.format(config.val.completion.timestamp_format
|
||||
.replace("'", "`")))
|
||||
|
||||
self._query = sql.Query(' '.join([
|
||||
@ -58,7 +58,7 @@ class HistoryCategory(QSqlQueryModel):
|
||||
|
||||
def _atime_expr(self):
|
||||
"""If max_items is set, return an expression to limit the query."""
|
||||
max_items = config.get('completion', 'web-history-max-items')
|
||||
max_items = config.val.completion.web_history_max_items
|
||||
# HistoryCategory should not be added to the completion in that case.
|
||||
assert max_items != 0
|
||||
|
||||
|
@ -21,8 +21,8 @@
|
||||
|
||||
from qutebrowser.config import config, configdata
|
||||
from qutebrowser.utils import objreg, log
|
||||
from qutebrowser.commands import cmdutils
|
||||
from qutebrowser.completion.models import completionmodel, listcategory
|
||||
from qutebrowser.commands import cmdutils
|
||||
|
||||
|
||||
def command():
|
||||
@ -135,26 +135,6 @@ def buffer():
|
||||
return model
|
||||
|
||||
|
||||
def bind(key):
|
||||
"""A CompletionModel filled with all bindable commands and descriptions.
|
||||
|
||||
Args:
|
||||
key: the key being bound.
|
||||
"""
|
||||
model = completionmodel.CompletionModel(column_widths=(20, 60, 20))
|
||||
cmd_text = objreg.get('key-config').get_bindings_for('normal').get(key)
|
||||
|
||||
if cmd_text:
|
||||
cmd_name = cmd_text.split(' ')[0]
|
||||
cmd = cmdutils.cmd_dict.get(cmd_name)
|
||||
data = [(cmd_text, cmd.desc, key)]
|
||||
model.add_category(listcategory.ListCategory("Current", data))
|
||||
|
||||
cmdlist = _get_cmd_completions(include_hidden=True, include_aliases=True)
|
||||
model.add_category(listcategory.ListCategory("Commands", cmdlist))
|
||||
return model
|
||||
|
||||
|
||||
def _get_cmd_completions(include_hidden, include_aliases, prefix=''):
|
||||
"""Get a list of completions info for commands, sorted by name.
|
||||
|
||||
|
@ -230,6 +230,7 @@ class ConfigCommands:
|
||||
|
||||
@cmdutils.register(instance='config-commands', star_args_optional=True)
|
||||
@cmdutils.argument('option', completion=configmodel.option)
|
||||
@cmdutils.argument('values', completion=configmodel.value)
|
||||
@cmdutils.argument('win_id', win_id=True)
|
||||
def set(self, win_id, option=None, *values, temp=False, print_=False):
|
||||
"""Set an option.
|
||||
@ -310,7 +311,7 @@ class ConfigCommands:
|
||||
|
||||
@cmdutils.register(instance='config-commands', maxsplit=1,
|
||||
no_cmd_split=True, no_replace_variables=True)
|
||||
@cmdutils.argument('command', completion=usertypes.Completion.bind)
|
||||
@cmdutils.argument('command', completion=configmodel.bind)
|
||||
def bind(self, key, command=None, *, mode='normal', force=False):
|
||||
"""Bind a key to a command.
|
||||
|
||||
|
@ -30,7 +30,7 @@ from PyQt5.QtWidgets import QWidget, QVBoxLayout, QApplication, QSizePolicy
|
||||
from qutebrowser.commands import runners, cmdutils
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.utils import (message, log, usertypes, qtutils, objreg, utils,
|
||||
jinja)
|
||||
jinja, debug)
|
||||
from qutebrowser.mainwindow import tabbedbrowser, messageview, prompt
|
||||
from qutebrowser.mainwindow.statusbar import bar
|
||||
from qutebrowser.completion import completionwidget, completer
|
||||
|
@ -77,6 +77,7 @@ class MessageView(QWidget):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self._messages = []
|
||||
self._vbox = QVBoxLayout(self)
|
||||
self._vbox.setContentsMargins(0, 0, 0, 0)
|
||||
self._vbox.setSpacing(0)
|
||||
@ -88,7 +89,6 @@ class MessageView(QWidget):
|
||||
config.instance.changed.connect(self._set_clear_timer_interval)
|
||||
|
||||
self._last_text = None
|
||||
self._messages = []
|
||||
|
||||
def sizeHint(self):
|
||||
"""Get the proposed height for the view."""
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
"""Fake objects/stubs."""
|
||||
|
||||
import collections
|
||||
from unittest import mock
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal, QPoint, QProcess, QObject
|
||||
@ -30,8 +29,7 @@ from PyQt5.QtNetwork import (QNetworkRequest, QAbstractNetworkCache,
|
||||
from PyQt5.QtWidgets import QCommonStyle, QLineEdit, QWidget, QTabBar
|
||||
|
||||
from qutebrowser.browser import browsertab
|
||||
from qutebrowser.config import configexc
|
||||
from qutebrowser.utils import usertypes, utils
|
||||
from qutebrowser.utils import usertypes
|
||||
from qutebrowser.mainwindow import mainwindow
|
||||
|
||||
|
||||
|
@ -29,7 +29,7 @@ import pytest
|
||||
from PyQt5.QtCore import QUrl
|
||||
|
||||
from qutebrowser.completion.models import miscmodels, urlmodel, configmodel
|
||||
from qutebrowser.config import sections, value
|
||||
from qutebrowser.config import sections, value, configdata, configtype
|
||||
from qutebrowser.utils import objreg
|
||||
|
||||
|
||||
@ -76,7 +76,8 @@ def _patch_cmdutils(monkeypatch, stubs, symbol):
|
||||
def _patch_configdata(monkeypatch, stubs, symbol):
|
||||
"""Patch the configdata module to provide fake data."""
|
||||
data = collections.OrderedDict([
|
||||
('general', sections.KeyValue(
|
||||
('general.time', configdata.Option(
|
||||
name='general.time'
|
||||
('time',
|
||||
value.SettingValue(stubs.FakeConfigType('fast', 'slow'),
|
||||
default='slow'),
|
||||
@ -141,8 +142,8 @@ def bookmarks(bookmark_manager_stub):
|
||||
@pytest.fixture
|
||||
def web_history(init_sql, stubs, config_stub):
|
||||
"""Fixture which provides a web-history object."""
|
||||
config_stub.data['completion'] = {'timestamp-format': '%Y-%m-%d',
|
||||
'web-history-max-items': -1}
|
||||
config_stub.completion.timestamp_format = '%Y-%m-%d'
|
||||
config_stub.completion.web_history_max_items = -1
|
||||
stub = history.WebHistory()
|
||||
objreg.register('web-history', stub)
|
||||
yield stub
|
||||
@ -182,7 +183,7 @@ def test_command_completion(qtmodeltester, monkeypatch, stubs, config_stub,
|
||||
"""
|
||||
_patch_cmdutils(monkeypatch, stubs,
|
||||
'qutebrowser.completion.models.miscmodels.cmdutils')
|
||||
config_stub.data['aliases'] = {'rock': 'roll'}
|
||||
config_stub.aliases = {'rock': 'roll'}
|
||||
key_config_stub.set_bindings_for('normal', {'s': 'stop',
|
||||
'rr': 'roll',
|
||||
'ro': 'rock'})
|
||||
@ -443,7 +444,7 @@ def test_url_completion_delete_history(qtmodeltester,
|
||||
def test_url_completion_zero_limit(config_stub, web_history, quickmarks,
|
||||
bookmarks):
|
||||
"""Make sure there's no history if the limit was set to zero."""
|
||||
config_stub.data['completion']['web-history-max-items'] = 0
|
||||
config_stub.completion.web_history_max_items = 0
|
||||
model = urlmodel.url()
|
||||
model.set_pattern('')
|
||||
category = model.index(2, 0) # "History" normally
|
||||
@ -520,32 +521,9 @@ def test_tab_completion_delete(qtmodeltester, fake_web_tab, app_stub,
|
||||
QUrl('https://duckduckgo.com')]
|
||||
|
||||
|
||||
def test_setting_section_completion(qtmodeltester, monkeypatch, stubs):
|
||||
def test_setting_option_completion(qtmodeltester, monkeypatch, stubs):
|
||||
module = 'qutebrowser.completion.models.configmodel'
|
||||
_patch_configdata(monkeypatch, stubs, module + '.configdata.DATA')
|
||||
_patch_config_section_desc(monkeypatch, stubs,
|
||||
module + '.configdata.SECTION_DESC')
|
||||
model = configmodel.section()
|
||||
model.set_pattern('')
|
||||
qtmodeltester.data_display_may_return_none = True
|
||||
qtmodeltester.check(model)
|
||||
|
||||
_check_completions(model, {
|
||||
"Sections": [
|
||||
('general', 'General/miscellaneous options.', None),
|
||||
('searchengines', 'Definitions of search engines ...', None),
|
||||
('ui', 'General options related to the user interface.', None),
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
def test_setting_option_completion(qtmodeltester, monkeypatch, stubs,
|
||||
config_stub):
|
||||
module = 'qutebrowser.completion.models.configmodel'
|
||||
_patch_configdata(monkeypatch, stubs, module + '.configdata.DATA')
|
||||
config_stub.data = {'ui': {'gesture': 'off',
|
||||
'mind': 'on',
|
||||
'voice': 'sometimes'}}
|
||||
model = configmodel.option('ui')
|
||||
model.set_pattern('')
|
||||
qtmodeltester.data_display_may_return_none = True
|
||||
@ -585,35 +563,6 @@ def test_setting_option_completion_valuelist(qtmodeltester, monkeypatch, stubs,
|
||||
})
|
||||
|
||||
|
||||
def test_setting_value_completion(qtmodeltester, monkeypatch, stubs,
|
||||
config_stub):
|
||||
module = 'qutebrowser.completion.models.configmodel'
|
||||
_patch_configdata(monkeypatch, stubs, module + '.configdata.DATA')
|
||||
config_stub.data = {'general': {'volume': '0'}}
|
||||
model = configmodel.value('general', 'volume')
|
||||
model.set_pattern('')
|
||||
qtmodeltester.data_display_may_return_none = True
|
||||
qtmodeltester.check(model)
|
||||
|
||||
_check_completions(model, {
|
||||
"Current/Default": [
|
||||
('0', 'Current value', None),
|
||||
('11', 'Default value', None),
|
||||
],
|
||||
"Completions": [
|
||||
('0', '', None),
|
||||
('11', '', None),
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
def test_setting_value_completion_empty(monkeypatch, stubs, config_stub):
|
||||
module = 'qutebrowser.completion.models.configmodel'
|
||||
_patch_configdata(monkeypatch, stubs, module + '.configdata.DATA')
|
||||
config_stub.data = {'general': {}}
|
||||
assert configmodel.value('general', 'typo') is None
|
||||
|
||||
|
||||
def test_bind_completion(qtmodeltester, monkeypatch, stubs, config_stub,
|
||||
key_config_stub):
|
||||
"""Test the results of keybinding command completion.
|
||||
|
Loading…
Reference in New Issue
Block a user