PyQt subclassing QSqlDatabase to make exceptions

Viewed 171

I love all of the goodness you get from QSqlDatabase and QSqlQuery and various models. But I would really like exceptions to be thrown when errors occur. So I thought maybe I could subclass QSqlDatabase to throw an exception when the open() method fails:

from PyQt5.QtWidgets import (QApplication, QMainWindow, QTableView)
from PyQt5.QtSql import (QSqlQuery, QSqlQueryModel, QSqlDatabase)
import sys

class ExceptionalDatabase(QSqlDatabase):

    #def addDatabase(self, *args, **kwargs):
        # what to put here? I need to return an instance of
        # ExceptionalDatabase, right?
        #
        # this doesn't work:
        # return super(ExceptionalDatabase, self).addDatabase(*args, **kwargs)

    def open(self, user=None, pwd=None):
        # this method will never be called, because addDatabase will
        # return a QSqlDatabase instance
        if user is None:
            retval = super(ExceptionalDatabase, self).open()
        else:
            retval = super(ExceptionalDatabase, self).open(user=user, password=pwd)

        if retval == False:
            raise ValueError(self.lastError().text())

app = QApplication(sys.argv)

fid = open('example.db', 'w')
fid.close()

db = ExceptionalDatabase.addDatabase("QSQLITE")
db.setDatabaseName('example.db')
db.open()

db.close()

sys.exit(app.exec_())

The main issue I have is I don't know how to handle the addDatabase method. It returns an instance of QSqlDatabase. But I want it to return an instance of ExceptionalDatabase. How would I get an instance of my class from addDatabase?

1 Answers

First of all addDatabase is a static method so you should not pass it self. On the other hand, a workaround is to establish the __class__ of the QSqlDataBase:

class ExceptionalDatabase(QSqlDatabase):
    @staticmethod
    def addDatabase(*args, **kwargs):
        db = QSqlDatabase.addDatabase(*args, **kwargs)
        db.__class__ = ExceptionalDatabase
        return db

    def open(self, user=None, pwd=None):
        if user is None:
            retval = super(ExceptionalDatabase, self).open()
        else:
            retval = super(ExceptionalDatabase, self).open(user=user, password=pwd)
        if retval == False:
            raise ValueError(self.lastError().text())
Related