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:
Florian Bruhin 2018-08-31 22:01:45 +02:00
parent 003f667d4f
commit 9fb794656b
2 changed files with 86 additions and 0 deletions

View File

@ -35,6 +35,40 @@ from qutebrowser.misc import objects, sql
_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):
"""History which only has the newest entry for each URL."""
@ -65,11 +99,18 @@ class WebHistory(sql.SqlTable):
'redirect': 'NOT NULL'},
parent=parent)
self.completion = CompletionHistory(parent=self)
self.metainfo = CompletionMetaInfo(parent=self)
if sql.Query('pragma user_version').run().value() < _USER_VERSION:
self.completion.delete_all()
if self.metainfo['force_rebuild']:
self.completion.delete_all()
self.metainfo['force_rebuild'] = False
if not self.completion:
# either the table is out-of-date or the user wiped it manually
self._rebuild_completion()
self.create_index('HistoryIndex', 'url')
self.create_index('HistoryAtimeIndex', 'atime')
self._contains_query = self.contains_query('url')

View File

@ -444,3 +444,48 @@ def test_user_version(hist, monkeypatch):
('example.com/1', '', 1),
('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']