Make it possible to force a history rebuild
This adds a new CompletionMetaInfo table which is a simple key/value store. Thanks to Python/sqlite duck typing, we can use that to store values of any type, even new ones in the future. Currently, the only allowed key is force_rebuild, which forces a rebuild of the CompletionHistory table. This will be needed for a future change.
This commit is contained in:
parent
003f667d4f
commit
9fb794656b
@ -35,6 +35,40 @@ from qutebrowser.misc import objects, sql
|
|||||||
_USER_VERSION = 2
|
_USER_VERSION = 2
|
||||||
|
|
||||||
|
|
||||||
|
class CompletionMetaInfo(sql.SqlTable):
|
||||||
|
|
||||||
|
"""Table containing meta-information for the completion."""
|
||||||
|
|
||||||
|
KEYS = {
|
||||||
|
'force_rebuild': False,
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__("CompletionMetaInfo", ['key', 'value'],
|
||||||
|
constraints={'key': 'PRIMARY KEY'})
|
||||||
|
for key, default in self.KEYS.items():
|
||||||
|
if key not in self:
|
||||||
|
self[key] = default
|
||||||
|
|
||||||
|
def __contains__(self, key):
|
||||||
|
if key not in self.KEYS:
|
||||||
|
raise KeyError(key)
|
||||||
|
query = self.contains_query('key')
|
||||||
|
return query.run(val=key).value()
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
if key not in self.KEYS:
|
||||||
|
raise KeyError(key)
|
||||||
|
query = sql.Query('SELECT value FROM CompletionMetaInfo '
|
||||||
|
'WHERE key = :key')
|
||||||
|
return query.run(key=key).value()
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
if key not in self.KEYS:
|
||||||
|
raise KeyError(key)
|
||||||
|
self.insert({'key': key, 'value': value}, replace=True)
|
||||||
|
|
||||||
|
|
||||||
class CompletionHistory(sql.SqlTable):
|
class CompletionHistory(sql.SqlTable):
|
||||||
|
|
||||||
"""History which only has the newest entry for each URL."""
|
"""History which only has the newest entry for each URL."""
|
||||||
@ -65,11 +99,18 @@ class WebHistory(sql.SqlTable):
|
|||||||
'redirect': 'NOT NULL'},
|
'redirect': 'NOT NULL'},
|
||||||
parent=parent)
|
parent=parent)
|
||||||
self.completion = CompletionHistory(parent=self)
|
self.completion = CompletionHistory(parent=self)
|
||||||
|
self.metainfo = CompletionMetaInfo(parent=self)
|
||||||
|
|
||||||
if sql.Query('pragma user_version').run().value() < _USER_VERSION:
|
if sql.Query('pragma user_version').run().value() < _USER_VERSION:
|
||||||
self.completion.delete_all()
|
self.completion.delete_all()
|
||||||
|
if self.metainfo['force_rebuild']:
|
||||||
|
self.completion.delete_all()
|
||||||
|
self.metainfo['force_rebuild'] = False
|
||||||
|
|
||||||
if not self.completion:
|
if not self.completion:
|
||||||
# either the table is out-of-date or the user wiped it manually
|
# either the table is out-of-date or the user wiped it manually
|
||||||
self._rebuild_completion()
|
self._rebuild_completion()
|
||||||
|
|
||||||
self.create_index('HistoryIndex', 'url')
|
self.create_index('HistoryIndex', 'url')
|
||||||
self.create_index('HistoryAtimeIndex', 'atime')
|
self.create_index('HistoryAtimeIndex', 'atime')
|
||||||
self._contains_query = self.contains_query('url')
|
self._contains_query = self.contains_query('url')
|
||||||
|
@ -444,3 +444,48 @@ def test_user_version(hist, monkeypatch):
|
|||||||
('example.com/1', '', 1),
|
('example.com/1', '', 1),
|
||||||
('example.com/2', '', 2),
|
('example.com/2', '', 2),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_force_rebuild(hist):
|
||||||
|
"""Ensure that completion is regenerated if we force a rebuild."""
|
||||||
|
hist.add_url(QUrl('example.com/1'), redirect=False, atime=1)
|
||||||
|
hist.add_url(QUrl('example.com/2'), redirect=False, atime=2)
|
||||||
|
hist.completion.delete('url', 'example.com/2')
|
||||||
|
|
||||||
|
hist2 = history.WebHistory()
|
||||||
|
assert list(hist2.completion) == [('example.com/1', '', 1)]
|
||||||
|
hist2.metainfo['force_rebuild'] = True
|
||||||
|
|
||||||
|
hist3 = history.WebHistory()
|
||||||
|
assert list(hist3.completion) == [
|
||||||
|
('example.com/1', '', 1),
|
||||||
|
('example.com/2', '', 2),
|
||||||
|
]
|
||||||
|
assert not hist3.metainfo['force_rebuild']
|
||||||
|
|
||||||
|
|
||||||
|
class TestCompletionMetaInfo:
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def metainfo(self):
|
||||||
|
return history.CompletionMetaInfo()
|
||||||
|
|
||||||
|
def test_contains_keyerror(self, metainfo):
|
||||||
|
with pytest.raises(KeyError):
|
||||||
|
'does_not_exist' in metainfo # pylint: disable=pointless-statement
|
||||||
|
|
||||||
|
def test_getitem_keyerror(self, metainfo):
|
||||||
|
with pytest.raises(KeyError):
|
||||||
|
metainfo['does_not_exist'] # pylint: disable=pointless-statement
|
||||||
|
|
||||||
|
def test_setitem_keyerror(self, metainfo):
|
||||||
|
with pytest.raises(KeyError):
|
||||||
|
metainfo['does_not_exist'] = 42
|
||||||
|
|
||||||
|
def test_contains(self, metainfo):
|
||||||
|
assert 'force_rebuild' in metainfo
|
||||||
|
|
||||||
|
def test_modify(self, metainfo):
|
||||||
|
assert not metainfo['force_rebuild']
|
||||||
|
metainfo['force_rebuild'] = True
|
||||||
|
assert metainfo['force_rebuild']
|
||||||
|
Loading…
Reference in New Issue
Block a user