[PyKDE] Now tackle dtor strangeness

Phil Thompson phil at river-bank.demon.co.uk
Sun Jan 26 01:17:01 GMT 2003


On Saturday 25 January 2003 11:07 pm, Hans-Peter Jansen wrote:
> On Saturday 25 January 2003 17:02, Phil Thompson wrote:
> > Thanks for putting the effort into this - it was very helpful. The bug is
> > that qspinbox.sip should say...
> >
> > bool eventFilter(QObject *,QEvent *);
> >
> > ...instead of...
> >
> > void eventFilter(QObject *,QEvent *);
> >
> > It will be fixed in tonight's snapshot.
>
> Thanks. Well done. I feel better now. But please have another look into
>
> these two:
> > > > qApp.quit(). Phil, it appears, that the QSpinBox base class
> > > > disappears while subclassed SpinBox event() handler is active. This
> > > > doesn't look right to me.
> > >
> > > While making both versions functional identical, I've rewritten the
> > > event decoder qEvent(), but couldn't believe my eyes: during
> > > qApp.quit() the value of the global defined qEventDict{} in the .py
> > > script is replaced with a None value somewhere under the covers! Please
> > > remove the
> > >
> > > Something is definitely going wrong here.
> >
> > I think this is just Python and Qt racing each other to tidy up. As the
> > behaviour of either isn't formally documented I think it's more a feature
> > rather than a bug.
>
> Well, I cannot see the feature aspect here. OTOH, this obfuscates the code,
> and it defies the principle of least surprise.
>
> I digged into this a bit further and found a way to get around these
> problems somehow:
>
> 1) The qEventDict does survive, if it is declared inside the qEvent
> function.
>
> 2) just keep a reference of QSpinBox, and call it, instead of the
> baseclass:
>
> class SpinBox(QSpinBox):
>     def __init__(self, minValue, maxValue, step = 1, parent = None, name =
> None): self.lastval = None
>         QSpinBox.__init__(self, minValue, maxValue, step, parent, name)
>         self.QSpinBox = QSpinBox
>
>     def event(self, e):
>         t = e.type()
>         print "SpinBox event:", qEvent(t)
>         return self.QSpinBox.event(self, e)
>
> Funny side note: it was enough to fix one of both sub classes this way to
> prevent attribute errors here. This is pretty undeterministic, and that's
> exactly the reason, why I don't like this behaviour...
>
> Phil, one would expect, that as long as a class exists, its baseclass
> should exist, either. The same goes for globals in module scope.

The class will exist (because the sub-class keeps a reference to it) but that 
doesn't mean that the reference to the class in (for example) the module's 
dictionary still exists.

The problem is that the order in which a dictionary's elements are deleted 
isn't very deterministic. In your example qEventDict is being removed from 
the module dictionary before the qEvent function is removed. By moving 
qEventDict into the qEvent function you guarantee it will exist whenever 
qEvent is called.

I would guess that the problem would also go away if you played with the names 
of qEvent and qEventDict so that they had hash values that caused them to 
appear in the module dictionary in the opposite order so that qEvent was 
deleted first.

Phil




More information about the PyQt mailing list