[PyQt] PyQt 5.7, QSqlQueryModel.data() sub-classed override bug?
J Barchan
jnbarchan at gmail.com
Wed May 9 08:04:27 BST 2018
On 8 May 2018 at 22:02, Phil Thompson <phil at riverbankcomputing.com> wrote:
>
> > On 8 May 2018, at 8:22 pm, J Barchan <jnbarchan at gmail.com> wrote:
> >
> >
> >
> > On 8 May 2018 at 18:14, Phil Thompson <phil at riverbankcomputing.com>
> wrote:
> > On 8 May 2018, at 9:04 am, J Barchan <jnbarchan at gmail.com> wrote:
> > >
> > > Now I'm finding that, with the fix discussed, while my overridden
> function definition correctly handles database NULLs, it "goes wrong" (as
> in, different behaviour from before) in certain other cases, returning a
> QVariant where it did not do so before (it returned the converted, native
> Python type).
> > >
> > > 1. So long as I do not override QSqlQueryModel.data() at all, there is
> absolutely no problem --- both database NULL and auto-conversion of
> non-NULL to Python native type work fine, and are distinct. This is the
> situation I need.
> > >
> > > 2. I need to override QSqlQueryModel.data() for my own purposes. If I
> write just:
> > > def data(self, index: QtCore.QModelIndex, role=QtCore.Qt.DisplayRole)
> -> typing.Any:
> > > value = super().data(index, role)
> > > return value
> > > Some data conversion happens, such that I no longer get NULL back
> where the value is NULL --- instead it is converted to '' if string or 0 if
> int. This was my original problem and is not acceptable.
> > >
> > > 3. Following our discussion, I change that to:
> > > def data(self, index: QtCore.QModelIndex, role=QtCore.Qt.DisplayRole)
> -> typing.Any:
> > > was_enabled = sip.enableautoconversion(QtCore.QVariant, False)
> > > value = super().data(index, role)
> > > sip.enableautoconversion(QtCore.QVariant, was_enabled)
> > > return value
> > > Now I correctly get whatever for database NULL, which works. However,
> some other path of code, on some quite different non-NULL value, gets back
> a QVariant where it used to get a string. I don't know what that path of
> code is, but I don't think I should care.
> > >
> > > So, what I need is: code which allows me to override
> QSqlQueryModel.data() but returns the original data() value unchanged,
> just like it used when I did not put any override in (case #1). It must do
> whatever to correctly deal with NULL & non-NULL, just like the
> non-overridden QSqlQueryModel.data() does.
> > >
> > > (In PyQt 5.7) What exact code can I put into the override to achieve
> just that, please? Surely that can be done, no?
> >
> > You can't have it both ways. Either you let PyQt automatically convert
> to/from QVariant (and you lose the detection of nulls) or you do it
> yourself (converting to Python using the value() method).
> >
> > By the way, I've just noticed a bug in the docs which says (incorrectly)
> that null QVariants are converted to None and vice versa.
> >
> > Phil
> >
> > Hi Phil,
> >
> > Thanks for your reply.
> >
> > I think one of us must be getting something wrong here. I wonder if
> you're still expecting me to understand something which is obvious to you
> but not to me.
> >
> > You can't have it both ways. Either you let PyQt automatically convert
> to/from QVariant (and you lose the detection of nulls) or you do it
> yourself (converting to Python using the value() method).
> >
> > I'm not asking to have anything both ways. I'm just asking how to
> write code so that the overridden method behaves absolutely identically to
> the base method it's overriding. Surely that must be possible?
> >
> > I remind you: when I have no override for QSqlQueryModel.data()
> everything behaves perfectly. I am saying: there is no problem, NULLs are
> handled as such and non-NULLs are correctly converted to their Python
> equivalent. I do not know how NULLs work (what they are returned as), but
> everything just works.
> >
> > As soon as I write an override which just returns the base method, it
> goes wrong on NULL. If I put it the sip.autoconversion(False), it works on
> NULL but now returns a QVariant where it used to return a Python native
> type, I think.
>
>
> Correct - because data() returns a QVariant. With the auto-conversion the
> Python native type is automatically converted to a QVariant.
>
> > All I want to know is: how can I write an override of
> QSqlQueryModel.data() in Python/PyQt like:
> >
> > def data(self, index: QtCore.QModelIndex, role=QtCore.Qt.DisplayRole) ->
> typing.Any:
> > value = super().data(index, role)
> > return value
> >
> > such that it returns just exactly the same as QSqlQueryModel.data()
> would have done, please, please, please?
>
>
> You already have it - with the calls to autoenableconversion().
>
> Phil
>
>
Correct - because data() returns a QVariant. With the auto-conversion the
> Python native type is automatically converted to a QVariant.
Fine. So are you saying I need to replicate the Python auto-conversion on
the result I get back because I had to suppress the autoconversion?, and
then return that? Is there a Pyton function, or what sort of code do I
need to write, to achieve the same result as whatever the autoconversion
would have done? Because I have no idea...
>
> You already have it - with the calls to autoenableconversion().
Phil, no I do not. I very carefully typed in that I had changed over to
precisely:
> > 3. Following our discussion, I change that to:
> > def data(self, index: QtCore.QModelIndex, role=QtCore.Qt.DisplayRole)
-> typing.Any:
> > was_enabled = sip.enableautoconversion(QtCore.QVariant, False)
> > value = super().data(index, role)
> > sip.enableautoconversion(QtCore.QVariant, was_enabled)
> > return value
> > Now I correctly get whatever for database NULL, which works. However,
some other path of code, on some quite different non-NULL value, gets back
a QVariant where it used to get a string. I don't know what that path of
code is, but I don't think I should care.
That's exactly what you are saying "You already have it - with the calls
to autoenableconversion()." about, correct? And I am saying: no, that code
returns whatever correct value in the NULL case which I was originally
complaining about, but now returns in other cases a QVariant back to my
code where it used to return, say, a string. Which then makes the calling
code go wrong. So with the calls to autoconversion it does *not* return
the same result as if I had never written the override, which is precisely
why I am stumped and asking the question....
--
Kindest,
Jonathan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20180509/49135689/attachment-0001.html>
More information about the PyQt
mailing list