2

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?

0

1 Answer 1

1

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())
Sign up to request clarification or add additional context in comments.

6 Comments

I cannot get addDatabase to work correctly. There is something it doesn't like about the signature. It says it's expecting QSqlDatabase.addDatabase(str, str connectionName=QLatin1String(QSqlDatabase.defaultConnection)) or QSqlDatabase.addDatabase(QSqlDriver, str connectionName=QLatin1String(QSqlDatabase.defaultConnection)). The only thing I could get to work was by passing bogus first argument: db = ExceptionalDatabase.addDatabase('', 'QSQLITE')
@bfris What tool gives you this warning? Are you using any linter or IDE?
I get this from command line. TypeError: arguments did not match any overloaded call: QSqlDatabase.addDatabase(str, str connectionName=QLatin1String(QSqlDatabase.defaultConnection)): not enough arguments QSqlDatabase.addDatabase(QSqlDriver, str connectionName=QLatin1String(QSqlDatabase.defaultConnection)): not enough arguments
How strange, which version of PyQt5 and python do you use? With PyQt5 5.14.2 and python 3.8.3 I don't see that problem on Linux.
Oh. This is embarrassing. You left self off of the signature and I included self. If I get rid of it, it works a treat with Python as old as 3.4.4 and Qt 5.5.1.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.