Merge Sql{Environment,Bug}Error with Sqlite{Environment,Bug}Error

This commit is contained in:
Florian Bruhin 2018-09-01 21:19:20 +02:00
parent 50ae2bf2f9
commit f5c92ded41
2 changed files with 37 additions and 56 deletions

View File

@ -27,59 +27,48 @@ from PyQt5.QtSql import QSqlDatabase, QSqlQuery, QSqlError
from qutebrowser.utils import log, debug from qutebrowser.utils import log, debug
class SqlEnvironmentError(Exception): class SqlError(Exception):
"""Base class for all SQL related errors."""
def __init__(self, msg, error=None):
super().__init__(msg)
self.error = error
def text(self):
"""Get a short text description of the error.
This is a string suitable to show to the user as error message.
"""
if self.error is None:
return str(self)
else:
return self.error.databaseText()
class SqlEnvironmentError(SqlError):
"""Raised on an error interacting with the SQL database. """Raised on an error interacting with the SQL database.
This is raised for errors resulting from the environment, where qutebrowser This is raised in conditions resulting from the environment (like a full
isn't to blame. disk or I/O errors), where qutebrowser isn't to blame.
""" """
def text(self): pass
return str(self)
class SqlBugError(Exception): class SqlBugError(SqlError):
"""Raised on an error interacting with the SQL database. """Raised on an error interacting with the SQL database.
This is raised for errors resulting from a qutebrowser bug. This is raised for errors resulting from a qutebrowser bug.
""" """
def text(self): pass
return str(self)
class SqliteEnvironmentError(SqlEnvironmentError):
"""A sqlite error which is caused by the environment.
This is raised in conditions like a full disk or I/O errors, where
qutebrowser isn't to blame.
"""
def __init__(self, msg, error):
super().__init__(msg)
self.error = error
def text(self):
return self.error.databaseText()
class SqliteBugError(SqlBugError):
"""A sqlite error which is caused by a bug in qutebrowser."""
def __init__(self, msg, error):
super().__init__(msg)
self.error = error
def text(self):
return self.error.databaseText()
def raise_sqlite_error(msg, error): def raise_sqlite_error(msg, error):
"""Raise either a SqliteBugError or SqliteEnvironmentError.""" """Raise either a SqlBugError or SqlEnvironmentError."""
log.sql.debug("SQL error:") log.sql.debug("SQL error:")
log.sql.debug("type: {}".format( log.sql.debug("type: {}".format(
debug.qenum_key(QSqlError, error.type()))) debug.qenum_key(QSqlError, error.type())))
@ -108,9 +97,9 @@ def raise_sqlite_error(msg, error):
errcode = error.nativeErrorCode() errcode = error.nativeErrorCode()
if (errcode in environmental_errors or if (errcode in environmental_errors or
(errcode == -1 and error.databaseText() in environmental_strings)): (errcode == -1 and error.databaseText() in environmental_strings)):
raise SqliteEnvironmentError(msg, error) raise SqlEnvironmentError(msg, error)
else: else:
raise SqliteBugError(msg, error) raise SqlBugError(msg, error)
def init(db_path): def init(db_path):
@ -221,7 +210,7 @@ class Query:
ok = self.query.execBatch() ok = self.query.execBatch()
try: try:
self._check_ok('execBatch', ok) self._check_ok('execBatch', ok)
except (SqliteBugError, SqliteEnvironmentError): except SqlError:
# Not checking the return value here, as we're failing anyways... # Not checking the return value here, as we're failing anyways...
db.rollback() db.rollback()
raise raise

View File

@ -37,11 +37,11 @@ def test_sqlerror(klass):
assert err.text() == text assert err.text() == text
class TestSqliteError: class TestSqlError:
@pytest.mark.parametrize('error_code, exception', [ @pytest.mark.parametrize('error_code, exception', [
('5', sql.SqliteEnvironmentError), # SQLITE_BUSY ('5', sql.SqlEnvironmentError), # SQLITE_BUSY
('19', sql.SqliteBugError), # SQLITE_CONSTRAINT ('19', sql.SqlBugError), # SQLITE_CONSTRAINT
]) ])
def test_environmental(self, error_code, exception): def test_environmental(self, error_code, exception):
sql_err = QSqlError("driver text", "db text", QSqlError.UnknownError, sql_err = QSqlError("driver text", "db text", QSqlError.UnknownError,
@ -52,7 +52,7 @@ class TestSqliteError:
def test_logging(self, caplog): def test_logging(self, caplog):
sql_err = QSqlError("driver text", "db text", QSqlError.UnknownError, sql_err = QSqlError("driver text", "db text", QSqlError.UnknownError,
'23') '23')
with pytest.raises(sql.SqliteBugError): with pytest.raises(sql.SqlBugError):
sql.raise_sqlite_error("Message", sql_err) sql.raise_sqlite_error("Message", sql_err)
lines = [r.message for r in caplog.records] lines = [r.message for r in caplog.records]
@ -64,16 +64,8 @@ class TestSqliteError:
assert lines == expected assert lines == expected
@pytest.mark.parametrize('base, sub', [
(sql.SqlEnvironmentError, sql.SqliteEnvironmentError),
(sql.SqlBugError, sql.SqliteBugError),
])
def test_subclass(self, base, sub):
with pytest.raises(base):
raise sub("text", QSqlError())
@pytest.mark.parametrize('klass', @pytest.mark.parametrize('klass',
[sql.SqliteEnvironmentError, sql.SqliteBugError]) [sql.SqlEnvironmentError, sql.SqlBugError])
def test_text(self, klass): def test_text(self, klass):
sql_err = QSqlError("driver text", "db text") sql_err = QSqlError("driver text", "db text")
err = klass("Message", sql_err) err = klass("Message", sql_err)
@ -103,7 +95,7 @@ def test_insert_replace(qtbot):
table.insert({'name': 'one', 'val': 11, 'lucky': True}, replace=True) table.insert({'name': 'one', 'val': 11, 'lucky': True}, replace=True)
assert list(table) == [('one', 11, True)] assert list(table) == [('one', 11, True)]
with pytest.raises(sql.SqliteBugError): with pytest.raises(sql.SqlBugError):
table.insert({'name': 'one', 'val': 11, 'lucky': True}, replace=False) table.insert({'name': 'one', 'val': 11, 'lucky': True}, replace=False)
@ -139,7 +131,7 @@ def test_insert_batch_replace(qtbot):
('one', 11, True), ('one', 11, True),
('nine', 19, True)] ('nine', 19, True)]
with pytest.raises(sql.SqliteBugError): with pytest.raises(sql.SqlBugError):
table.insert_batch({'name': ['one', 'nine'], table.insert_batch({'name': ['one', 'nine'],
'val': [11, 19], 'val': [11, 19],
'lucky': [True, True]}) 'lucky': [True, True]})
@ -236,7 +228,7 @@ def test_version():
class TestSqlQuery: class TestSqlQuery:
def test_prepare_error(self): def test_prepare_error(self):
with pytest.raises(sql.SqliteBugError) as excinfo: with pytest.raises(sql.SqlBugError) as excinfo:
sql.Query('invalid') sql.Query('invalid')
expected = ('Failed to prepare query "invalid": "near "invalid": ' expected = ('Failed to prepare query "invalid": "near "invalid": '